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

2013年4月25日 22:34:43 -0700

On 04/25/2013 07:13 PM, Nick Coghlan wrote:
On Fri, Apr 26, 2013 at 8:29 AM, Barry Warsaw <[email protected]> wrote:
On Apr 25, 2013, at 03:19 PM, Guido van Rossum wrote:
Clearly this is a trick question. :-)
A bit, yes. :)
I was told when this was brought up previously (a week ago?) that it
would be simple to make it truly the same class.
It didn't sound simple to me, but I haven't seen any actual code yet.
I'm the one who said I didn't see any obvious barriers to the merger,
but I've realised there is one, and it's similar to one namedtuple
struggles with: how to handle method definitions.
[snip]
With a merged design, it becomes *really* hard to give the instances
custom behaviour, because the metaclass will somehow have to
differentiate between namespace entries that are intended to be
callables, and those which are intended to be instances of the enum.
This is not an easy problem to solve.
I'm probably going to regret asking this, but what's difficult with the 
following?
8<-----------------------------------------------------------------------------------------
class EnumDict(dict):
 """
 automatically assigns the next _int for an enum
 """
 def __init__(yo):
 super().__init__()
 yo._allow_duplicates = False
 yo._value = 1
 yo._base = 1
 yo._enums = []
 yo._type = None # object means enum, anything else means all must be of 
that type
 def __setitem__(yo, key, new_value):
 """
 main purpose is to support auto-numbering of members
 """
 existing = yo.get(key)
 if type(existing) is attrs: # attrs is a helper class
 raise TypeError('Attempted to reuse key: %s' % key)
 if not key[:2] == key[-2:] == '__':
 old_value = None
 if isinstance(new_value, attrs):
 old_value = new_value
 if new_value.integer is None:
 new_value = yo._value
 else:
 new_value = new_value.integer
 if not isinstance(new_value, int):
 raise TypeError(
 "an enum integer must be an instance of type <int>, not 
%s"
 % type(new_value)
 )
 if not callable(new_value): # this if-else is probably not final
 if (isinstance(new_value, int) and old_value is not None
 or yo._type in (object, )):
 yo._check_duplicate_integer(new_value, key)
 yo._value = new_value
 yo._inc_integer()
 yo._enums.append(key)
 new_value = attrs(integer=new_value)
 elif yo._type is None: # random bunch of named constants
 yo._check_duplicate_integer(new_value, key)
 value = yo._value
 yo._inc_integer()
 yo._enums.append(key)
 new_value = attrs(value=new_value, integer=value)
 elif isinstance(new_value, yo._type): # single type of named 
constants
 if isinstance(yo._type, int):
 value = new_value
 else:
 value = yo._value
 yo._check_duplicate_integer(value, key)
 yo._inc_integer()
 yo._enums.append(key)
 new_value = attrs(value=new_value, integer=value)
 if old_value is not None:
 new_value, old_value.integer = old_value, new_value.integer
 dict.__setitem__(yo, key, new_value)
 def _inc_integer(yo):
 if yo._base == 1:
 yo._value += 1
 else:
 if yo._value == 0:
 value = 1
 else:
 value = floor(log(yo._value, 2))
 value = 2 ** value
 value <<= 1
 yo._value = value
 def _check_duplicate_integer(yo, new_value, key):
 for name, value in yo.items():
 if not isinstance(value, attrs):
 continue
 if value.integer == new_value and name != key and not 
yo._allow_duplicates:
 raise TypeError('duplicate value for %s: %d' % (key, value))
8<-------------------------------------------------------------------------------------------
Basically, if the assigned value is not `attrs` or a literal of the same type 
as the enum, the metaclass ignores it.
--
~Ethan~
_______________________________________________
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