[Python-ideas] Allow Enum members to refer to each other during execution of body

Antony Lee antony.lee at berkeley.edu
Wed Jul 10 04:27:06 CEST 2013


"Part of the problem here would be maintaining the linkage when the temp
enum object from _EnumDict was translated into an actual Enum member."

I implemented the required behavior here: https://github.com/anntzer/enum
Instead of creating a new enum object from the temp object stored in
_EnumDict, I directly change the class of the temp object to its actual
value once that class is built, thus keeping references correct (see
test_backward_reference).  However, this behavior breaks down if the Enum
class also inherits from a type with a different layout (e.g., int),
because I can't change the class of such objects.  In fact, even

class A(int): pass
class B(int): pass
A().__class__ = B

fails (which is puzzling to me... I understand that you can't transform an
instance of an int-subclass into an instance of an str-subclass), but here
both classes should have the same layout...

On the other hand IntEnums shouldn't need that kind of behavior anyways, so
I just kept the old implementation for them (for any class for which
instances can't be instantiated by object.__new__(cls), in fact).

I haven't worked on forward-references but this should be not too hard to
implement either: just add a __missing__ to _EnumDict (cf. the discussion
on implicit enums) that creates temporary placeholder members on the fly.
When these members are actually defined, initialize them.  When class body
finishes to execute, check that all placeholders have been initialized,
throwing an error otherwise.

Antony


2013/7/8 Antony Lee <antony.lee at berkeley.edu>

> Currently, during the execution of the body of the Enum declaration,
> member names are bound to the values, not to the Enum members themselves.
> For example
>
> class StateMachine(Enum):
>     A = {}
>     B = {1: A} # e.g. a transition table
>
> StateMachine.B[1] == {}, when one could have expected StateMachine.B[1] ==
> StateMachine.A
>
> It seems to me that a behavior where member names are bound to the members
> instead of being bound to the values is more useful, as one can easily
> retrieve the values from the members but not the other way round (at least
> during the execution of class body).
>
> Initially, I thought that this could be changed by modifying _EnumDict, so
> that its __setitem__ method sets the member in the dict, instead of the
> value, but in fact this doesn't work because while the values are being set
> in the _EnumDict the class itself doesn't exist yet (and for good reason:
> the __init__ and __new__ methods may be defined later but there is no way
> to know that).  However, a possible solution could to momentarily create
> Enum members as instances of some dummy class, and then later, after
> execution of class body has completed, change the members' class to the
> actual Enum and initialize them as needed (if an __init__ or a __new__ are
> actually defined).  Well, there are limitations with this approach (e.g.
> the members are not fully initialized before class body finishes to
> execute) but this seems better than the current behavior(?)
>
> Best,
>
> Antony
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20130709/b999c7c9/attachment.html>


More information about the Python-ideas mailing list