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?
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 aliases 1 .
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.