Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library

2013年4月27日 11:47:36 -0700

On 27/04/13 12:51, Ethan Furman wrote:
On 04/26/2013 07:29 PM, Glenn Linderman wrote:
[...]
class Color( Enum ):
 Enum.__enumerationItems__(
 red=1,
 green=2,
 blue=3,
 )
 # other methods and assignments
Or, if we go with the metaclass magic of re-using the class/type name (and who 
doesn't love metaclass magic??):
class Color(Enum):
 red = Color(1)
 green = Color(2)
 blue = Color 3)
 look_ma_not_an_enum = 4
and from a later email:
The solution I like best is the helper class (called, originally enough, enum), 
and only those items get transformed:
class Planet(IntEnum):
 MERCURY = enum(1)
 VENUS = enum(2)
 EARTH = enum(3)
 rough_pi = 3 # not transformed
I'm sorry, but all these suggestions are getting the API completely backwards 
by making the common case harder than the rare case.
We're creating an Enum, right? So the *common case* is to populate it with enum 
values. 99% of the time, enumerated values will be all that we want from an 
enum. So that's the case that needs to be simple, not the rare case where you 
have a non enum value in an enum class.
The common case (enum values in an Enum class) should be easy, and the rare 
cases (ordinary class-like attributes) possible.
Explicit is better than implicit: if you want something to *not* be processed 
by the Enum metaclass, you have to explicitly mark it as special. Dunders 
excepted, because they *are* special enough to break the rules. Since dunders 
are reserved for Python, I'm happy with a rule that says that dunders cannot be 
set as enum values (at least not via the metaclass). Otherwise, everything 
inside an Enum class is treated as an enum value unless explicitly flagged as 
not.
Here's a dirty hack that demonstrates what I'm talking about.
class EnumValue:
 # Mock EnumValue class.
 def __new__(cls, name, obj):
 print("making enum {!s} from {!r}".format(name, obj))
 return obj
class MetaEnum(type):
 def __new__(meta, name, bases, namespace):
 cls = super().__new__(meta, name, bases, {})
 for name, value in namespace.items():
 if meta.isspecial(value):
 value = value.original
 elif not meta.isdunder(name):
 value = EnumValue(name, value)
 setattr(cls, name, value)
 return cls
 @staticmethod
 def isdunder(name):
 return name.startswith('__') and name.endswith('__')
 @staticmethod
 def isspecial(obj):
 return isinstance(obj, skip)
class skip:
 def __init__(self, obj):
 self.original = obj
class Example(metaclass=MetaEnum):
 red = 1
 blue = 2
 green = lambda: 'good lord, even functions can be enums!'
 def __init__(self, count=3):
 self.count = count
 food = skip('spam')
 @skip
 def spam(self):
 return self.count * self.food
--
Steven
_______________________________________________
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to