diff -r 78145e6ffb40 Lib/enum.py --- a/Lib/enum.py Wed Feb 18 08:56:33 2015 -0500 +++ b/Lib/enum.py Fri Feb 20 01:28:10 2015 -0800 @@ -159,20 +159,24 @@ class EnumMeta(type): # 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) enum_class._member_map_[member_name] = enum_member + # performance boost for any member that would not shadow + # a DynamicClassAttribute + if not hasattr(enum_class, member_name): + setattr(enum_class, 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 # double check that repr and friends are not the mixin's or various # things break (such as pickle) @@ -461,21 +465,21 @@ class Enum(metaclass=EnumMeta): self.__class__.__name__, self._name_, self._value_) def __str__(self): return "%s.%s" % (self.__class__.__name__, self._name_) def __dir__(self): added_behavior = [ m for cls in self.__class__.mro() for m in cls.__dict__ - if m[0] != '_' + if m[0] != '_' and m not in self._member_map_ ] return (['__class__', '__doc__', '__module__', 'name', 'value'] + added_behavior) def __format__(self, format_spec): # mixed-in Enums should use the mixed-in type's __format__, otherwise # we can get strange results with the Enum name showing up instead of # the value # pure Enum branch