[Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library (original) (raw)
Steven D'Aprano steve at pearwood.info
Sat Apr 27 20:45:32 CEST 2013
- Previous message: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
- Next message: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
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) lookmanotanenum = 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) roughpi = 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
- Previous message: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
- Next message: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]