forked from ElectricRCAircraftGuy/eRCaGuy_hello_world
-
Notifications
You must be signed in to change notification settings - Fork 0
/
enum_practice.py
executable file
·358 lines (294 loc) · 11.9 KB
/
enum_practice.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
#!/usr/bin/python3
"""
This file is part of eRCaGuy_hello_world: https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world
GS
Aug. 2021
Demonstrate how to use Enums (Enum class objects) in Python.
References:
1. [Official Python3 documentation] https://docs.python.org/3/library/enum.html
Run command:
./enum_practice.py
OR:
python3 enum_practice.py
"""
from enum import Enum, IntEnum
# ==============================
print("======= EXAMPLE 1: enum basics, incl. member attributes =======\n")
# Create an enum class called "Fruit", with the following enum **names** and **values**
# inside of it.
class Fruit(Enum):
APPLE = 1
PEAR = 2
BANANA = 3
KIWI = "kiwi"
LEMON = "lemon"
# Note: the `.value` member variable contains the enum's assigned value, which can be an integer,
# string, etc. The official documentation (link above) states:
#
# """
# Note: Enum member values
#
# Member values can be anything: int, str, etc.. If the exact value is unimportant you may use auto
# instances and an appropriate value will be chosen for you. Care must be taken if you mix auto with
# other values.
# """
# Note: for the % print notation in Python, follow the C & C++ `printf()` documentation here:
# http://www.cplusplus.com/reference/cstdio/printf/
fruit = Fruit.APPLE
print("enum scoped name = %-15s enum name = %-10s enum value = %s" % (fruit, fruit.name, fruit.value))
fruit = Fruit.PEAR
print("enum scoped name = %-15s enum name = %-10s enum value = %s" % (fruit, fruit.name, fruit.value))
fruit = Fruit.BANANA
print("enum scoped name = %-15s enum name = %-10s enum value = %s" % (fruit, fruit.name, fruit.value))
fruit = Fruit.KIWI
print("enum scoped name = %-15s enum name = %-10s enum value = %s" % (fruit, fruit.name, fruit.value))
fruit = Fruit.LEMON
print("enum scoped name = %-15s enum name = %-10s enum value = %s" % (fruit, fruit.name, fruit.value))
print()
print(fruit.__dict__) # see what all is inside of the fruit **Enum class**.
print("---")
print(fruit._value_)
print(fruit.value) # same as above, but more-commonly-used
print(fruit._name_)
print(fruit.name) # same as above, but more-commonly-used
print(fruit.__objclass__)
print("---")
print(fruit._value_ is fruit.value) # See if these "values" truly are the same type
print(fruit._value_ == fruit.value) # See if these "values" represent the same values
print("---")
print(fruit)
print(str(fruit)) # same as above
print()
print(fruit.__objclass__)
print(Fruit) # same as above
print(type(fruit)) # same as above in this case
print()
# ==============================
print("======= EXAMPLE 2: enum multi-class inheritance, and iteration =======\n")
# Note: just like with any class, your custom Enum class can inherit from other class types too,
# such as `int` or `str`, in addition to `Enum`. If you inherit from `str` as well, it forces
# all of your "values" in the enum to be of type `str`, even when they look like integers.
class StrEnum(str, Enum):
ENUM1 = "hey"
ENUM2 = "how"
ENUM3 = "are"
ENUM4 = "you?"
# NB!: since this Enum class also inherits from the `str` class, this value gets stored as the
# **string** "1234" even though it looks like an integer!
ENUM5 = 1234
strEnum = StrEnum.ENUM5
print(strEnum.value*2) # prints the **string** "1234" twice in a row, so you will see "12341234"
# How to **iterate over an entire enum class** (let's also prove the values are strings too):
print()
for enum in StrEnum:
print("%-15s %8s = %-8s type(enum.value) is str? %s" % (enum, enum.name, enum.value,
type(enum.value) is str))
print()
for enum in Fruit:
print("%-15s %8s = %-8s type(enum.value) is str? %s" % (enum, enum.name, enum.value,
type(enum.value) is str))
print()
# And, a few more prints for good measure. Here are 2 ways to access the enum:
# 1. Access the enum **via a variable** (`fruit`) which is of this type
fruit = Fruit.APPLE
print("%-15s %8s = %-8s type(fruit.value) is str? %s" % (fruit, fruit.name, fruit.value,
type(fruit.value) is str))
# OR 2. Access an enum **directly via its scoped class name** (ex: `Fruit.APPLE`).
# The output is the same as above!
print("%-15s %8s = %-8s type(Fruit.APPLE.value) is str? %s" % (Fruit.APPLE, Fruit.APPLE.name,
Fruit.APPLE.value, type(Fruit.APPLE.value) is str))
print()
# ==============================
print("======= EXAMPLE 3: enum comparisons, with regular enums, string enums, and integer " +
"enums =======\n")
# REGULAR ENUMS:
# Regular enums are Enum types, NOT string types, so they are NOT equal to enums or strings.
#
# STRING ENUMS:
# However, when you inherit from both the `str` AND `Enum` classes you get the `str` implementation
# of `__eq__`(), which means `strEnum.COLOR1 == "red"` returns True, instead of False like it would
# do for regular enums.
#
# INTEGER ENUMS:
# Similar behavior exists for the `IntEnum` class, which is the same as inheriting from both the
# `int` and `Enum` classes. Therefore `intEnum` types can act like both enums AND integers, kind of
# like enums in C, but NOT enum classes in C++ (unless cast to `int`s).
# - See also: https://docs.python.org/3/library/enum.html#intenum
# A regular enum: inherits from the `Enum` class
class regularEnum(Enum):
COLOR1 = "red" # value "red" is of type `str`
COLOR2 = "blue" # value "blue" is of type `str`
COLOR3 = 7 # value 7 is of type `int`
# A string enum: inherits from the `str` and `Enum` classes
class strEnum(str, Enum):
COLOR1 = "red" # value "red" is of type `str`
COLOR2 = "blue" # value "blue" is of type `str`
COLOR3 = 7 # value 7 is of type `str` <==== NOTICE THIS ONE IS A str TOO!
# An integer enum: inherits from the `int` and `Enum` classes
class intEnum1(int, Enum):
# COLOR1 = "red" # ValueError: invalid literal for int() with base 10: 'red'
COLOR1 = 9
COLOR2 = 8
COLOR3 = 7
# OR (same thing as above, I think) an integer enum inherits from the `intEnum` class
class intEnum2(IntEnum):
# COLOR1 = "red" # ValueError: invalid literal for int() with base 10: 'red'
COLOR1 = 9
COLOR2 = 8
COLOR3 = 7
print("Enums themselves are NOT strings or integers! They are of type enum!")
print(type(regularEnum.COLOR1) is str) # False
print(type(regularEnum.COLOR2) is str) # False
print(type(regularEnum.COLOR3) is int) # False
print(type(regularEnum.COLOR1))
print(type(regularEnum.COLOR2))
print(type(regularEnum.COLOR3))
print()
print("However, their **values** can be `str` or `int` types")
print(type(regularEnum.COLOR1.value) is str) # True, its value is a string
print(type(regularEnum.COLOR2.value) is str) # True, its value is a string
print(type(regularEnum.COLOR3.value) is int) # True, its value is an integer
print("types of their values can be `str` or `int`")
print(type(regularEnum.COLOR1.value))
print(type(regularEnum.COLOR2.value))
print(type(regularEnum.COLOR3.value))
print("types of their names are `str`")
print(type(regularEnum.COLOR1.name))
print(type(regularEnum.COLOR2.name))
print(type(regularEnum.COLOR3.name))
print()
print("Therefore, since regular enums are enums, NOT strings or ints, the following are all False")
print(regularEnum.COLOR1 == "red") # False
print(regularEnum.COLOR2 == "blue") # False
print(regularEnum.COLOR3 == 7) # False
print()
print("BUT, the strEnum is different! Only the last one is False")
print(strEnum.COLOR1 == "red") # True
print(strEnum.COLOR2 == "blue") # True
print(strEnum.COLOR3 == 7) # False
print("...and this is True")
print(strEnum.COLOR3 == "7") # True
print()
print("And, integer enums can compare as integers too, as shown here")
print("intEnum1:")
print(intEnum1.COLOR1 == 9) # True
print(intEnum1.COLOR2 == 8) # True
print(intEnum1.COLOR3 == 7) # True
print("intEnum2:")
print(intEnum2.COLOR1 == 9) # True
print(intEnum2.COLOR2 == 8) # True
print(intEnum2.COLOR3 == 7) # True
print("intEnum1 compared to intEnum2:")
print(intEnum1.COLOR1 == intEnum2.COLOR1) # True
print(intEnum1.COLOR2 == intEnum2.COLOR2) # True
print(intEnum1.COLOR3 == intEnum2.COLOR3) # True
print("BUT, regular enums do NOT compare as integers even when they store integer values, so " +
"this is False!")
print(regularEnum.COLOR3 == intEnum2.COLOR3) # False! Even though both of these have integer values
# equal to 7, this is False because a regular enum
# is an enum type, NOT an integer type.
print("...these are all True though (both of their integer values are 7)")
print(regularEnum.COLOR3.value == intEnum2.COLOR3.value) # True
print(regularEnum.COLOR3.value == 7) # True
print(intEnum2.COLOR3.value == 7) # True
print()
print("type information (just for general awareness):")
print(type(intEnum1.COLOR1))
print(type(intEnum2.COLOR1))
print(type(intEnum1))
print(type(intEnum2))
print()
"""
SAMPLE OUTPUT:
eRCaGuy_hello_world/python$ ./enum_practice.py
======= EXAMPLE 1: enum basics, incl. member attributes =======
enum scoped name = Fruit.APPLE enum name = APPLE enum value = 1
enum scoped name = Fruit.PEAR enum name = PEAR enum value = 2
enum scoped name = Fruit.BANANA enum name = BANANA enum value = 3
enum scoped name = Fruit.KIWI enum name = KIWI enum value = kiwi
enum scoped name = Fruit.LEMON enum name = LEMON enum value = lemon
{'_value_': 'lemon', '_name_': 'LEMON', '__objclass__': <enum 'Fruit'>}
---
lemon
lemon
LEMON
LEMON
<enum 'Fruit'>
---
True
True
---
Fruit.LEMON
Fruit.LEMON
<enum 'Fruit'>
<enum 'Fruit'>
<enum 'Fruit'>
======= EXAMPLE 2: enum multi-class inheritance, and iteration =======
12341234
StrEnum.ENUM1 ENUM1 = hey type(enum.value) is str? True
StrEnum.ENUM2 ENUM2 = how type(enum.value) is str? True
StrEnum.ENUM3 ENUM3 = are type(enum.value) is str? True
StrEnum.ENUM4 ENUM4 = you? type(enum.value) is str? True
StrEnum.ENUM5 ENUM5 = 1234 type(enum.value) is str? True
Fruit.APPLE APPLE = 1 type(enum.value) is str? False
Fruit.PEAR PEAR = 2 type(enum.value) is str? False
Fruit.BANANA BANANA = 3 type(enum.value) is str? False
Fruit.KIWI KIWI = kiwi type(enum.value) is str? True
Fruit.LEMON LEMON = lemon type(enum.value) is str? True
Fruit.APPLE APPLE = 1 type(fruit.value) is str? False
Fruit.APPLE APPLE = 1 type(Fruit.APPLE.value) is str? False
======= EXAMPLE 3: enum comparisons, with regular enums, string enums, and integer enums =======
Enums themselves are NOT strings or integers! They are of type enum!
False
False
False
<enum 'regularEnum'>
<enum 'regularEnum'>
<enum 'regularEnum'>
However, their **values** can be `str` or `int` types
True
True
True
types of their values can be `str` or `int`
<class 'str'>
<class 'str'>
<class 'int'>
types of their names are `str`
<class 'str'>
<class 'str'>
<class 'str'>
Therefore, since regular enums are enums, NOT strings or ints, the following are all False
False
False
False
BUT, the strEnum is different! Only the last one is False
True
True
False
...and this is True
True
And, integer enums can compare as integers too, as shown here
intEnum1:
True
True
True
intEnum2:
True
True
True
intEnum1 compared to intEnum2:
True
True
True
BUT, regular enums do NOT compare as integers even when they store integer values, so this is False!
False
...these are all True though (both of their integer values are 7)
True
True
True
type information (just for general awareness):
<enum 'intEnum1'>
<enum 'intEnum2'>
<class 'enum.EnumMeta'>
<class 'enum.EnumMeta'>
"""