I don't understand why this Enum doesn't have all the members I defined, when I assign a dict as each member's value:
from enum import Enum
class Token(Enum):
facebook = {
'access_period': 0,
'plan_name': ''}
instagram = {
'access_period': 0,
'plan_name': ''}
twitter = {
'access_period': 0,
'plan_name': ''}
if __name__ == "__main__":
print(list(Token))
The output is:
[<Token.twitter: {'plan_name': '', 'access_period': 0}>]
… but I expected something like:
[<Token.facebook: {'plan_name': '', 'access_period': 0}>,
<Token.instagram: {'plan_name': '', 'access_period': 0}>,
<Token.twitter: {'plan_name': '', 'access_period': 0}>]
Why aren't all the members shown?
By definition, the enumeration member values are unique. However, you can create different member names with the same values.
To check if a value exists in an enum in Python: Use a list comprehension to get a list of all of the enum's values. Use the in operator to check if the value is present in the list. The in operator will return True if the value is in the list.
Enum is a class in python for creating enumerations, which are a set of symbolic names (members) bound to unique, constant values. The members of an enumeration can be compared by these symbolic anmes, and the enumeration itself can be iterated over. An enum has the following characteristics.
Syntax : enum.auto() Automatically assign the integer value to the values of enum class attributes. Example #1 : In this example we can see that by using enum. auto() method, we are able to assign the numerical values automatically to the class attributes by using this method.
Enum enforces unique values for the members. Member definitions with the same value as other definitions will be treated as aliases.
Demonstration:
Token.__members__
# OrderedDict([('twitter',
# <Token.twitter: {'plan_name': '', 'access_period': 0}>),
# ('facebook',
# <Token.twitter: {'plan_name': '', 'access_period': 0}>),
# ('instagram',
# <Token.twitter: {'plan_name': '', 'access_period': 0}>)])
assert Token.instagram == Token.twitter
The defined names do all exist, however they are all mapped to the same member.
Have a look at the source code if you are interested:
# [...]
# If another member with the same value was already defined, the
# new member becomes an alias to the existing one.
for name, canonical_member in enum_class._member_map_.items():
if canonical_member._value_ == enum_member._value_:
enum_member = canonical_member
break
else:
# Aliases don't appear in member names (only in __members__).
enum_class._member_names_.append(member_name)
# performance boost for any member that would not shadow
# a DynamicClassAttribute
if member_name not in base_attributes:
setattr(enum_class, member_name, enum_member)
# now add to _member_map_
enum_class._member_map_[member_name] = enum_member
try:
# This may fail if value is not hashable. We can't add the value
# to the map, and by-value lookups for this value will be
# linear.
enum_class._value2member_map_[value] = enum_member
except TypeError:
pass
# [...]
Further, it seems to me that you want to exploit the Enum class to modify the value (the dictionary) during run-time. This is strongly discouraged and also very unintuitive for other people reading/using your code. An enum is expected to be made of constants.
As @MichaelHoff noted, the behavior of Enum
is to consider names with the same values to be aliases1.
You can get around this by using the Advanced Enum
2 library:
from aenum import Enum, NoAlias
class Token(Enum):
_settings_ = NoAlias
facebook = {
'access_period': 0,
'plan_name': '',
}
instagram = {
'access_period': 0,
'plan_name': '',
}
twitter = {
'access_period': 0,
'plan_name': '',
}
if __name__ == "__main__":
print list(Token)
Output is now:
[
<Token.twitter: {'plan_name': '', 'access_period': 0}>,
<Token.facebook: {'plan_name': '', 'access_period': 0}>,
<Token.instagram: {'plan_name': '', 'access_period': 0}>,
]
To reinforce what Michael said: Enum
members are meant to be constants -- you shouldn't use non-constant values unless you really know what you are doing.
A better example of using NoAlias
:
class CardNumber(Enum):
_order_ = 'EIGHT NINE TEN JACK QUEEN KING ACE' # only needed for Python 2.x
_settings_ = NoAlias
EIGHT = 8
NINE = 9
TEN = 10
JACK = 10
QUEEN = 10
KING = 10
ACE = 11
1 See this answer for the standard Enum
usage.
2 Disclosure: I am the author of the Python stdlib Enum
, the enum34
backport, and the Advanced Enumeration (aenum
) library.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With