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

Haoyi Li haoyi.sg at gmail.com
Tue Jul 9 03:03:27 CEST 2013


> then the other methods can either dereference the name with an
__getitem__ look-up, or the class can be post-processed with a decorator to
change the strings back to actual members... hmmm, maybe a post_process
hook in the metaclass would make sense?

Having real strings be part of the enums data members is a pretty common
thing, and working through and trying to identify the linkage-strings from
normal-strings seems very magical to me. Is there some metaclass-magic way
to intercept the usage of A, to instead put the enum instance there?

Also, for this to be useful for your described use case, (state machines
yay!) you'd probably want to be able to define back/circular references,
which i think isn't currently possible. The obvious thing to do would be to
somehow make the RHS of the assignments lazy, which would allow
out-of-order and circular assignments with a very nice, unambigious:

class StateMachine(Enum):
    "Useless ping-pong state machine"
    A = {1: B}
    B = {1: A}

But short of using macros to do an AST transform, I don't know if such a
thing is possible at all.

-Haoyi


On Tue, Jul 9, 2013 at 8:12 AM, Ethan Furman <ethan at stoneleaf.us> wrote:

> On 07/08/2013 02:27 PM, Antony Lee wrote:
>
>> 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(?)
>>
>
> Part of the problem here would be maintaining the linkage when the temp
> enum object from _EnumDict was translated into an actual Enum member.
>
> One possible work around is to store the name of the member instead:
>
>   class StateMachine(Enum):
>       A = {}
>       B = {1:'A'}
>
> then the other methods can either dereference the name with an __getitem__
> look-up, or the class can be post-processed with a decorator to change the
> strings back to actual members... hmmm, maybe a post_process hook in the
> metaclass would make sense?
>
> --
> ~Ethan~
> ______________________________**_________________
> Python-ideas mailing list
> Python-ideas at python.org
> http://mail.python.org/**mailman/listinfo/python-ideas<http://mail.python.org/mailman/listinfo/python-ideas>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20130709/ee682614/attachment.html>


More information about the Python-ideas mailing list