Sì, c'è, ed è la mia ricetta preferita finora. Come bonus, non è necessario specificare il valore intero. Ecco un esempio:
class AddressSegment(AutoEnum):
misc = "not currently tracked"
ordinal = "N S E W NE NW SE SW"
secondary = "apt bldg floor etc"
street = "st ave blvd etc"
Si potrebbe chiedere perché non mi resta che "N S E W NE NW SE SW"
essere il valore di ordinal
? Perché quando ottengo il suo repr seeing <AddressSegment.ordinal: 'N S E W NE NW SE SW'>
diventa un po 'goffo, ma avere queste informazioni prontamente disponibili nella docstring è un buon compromesso.
Ecco la ricetta per l'Enum:
class AutoEnum(enum.Enum):
"""
Automatically numbers enum members starting from 1.
Includes support for a custom docstring per member.
"""
__last_number__ = 0
def __new__(cls, *args):
"""Ignores arguments (will be handled in __init__."""
value = cls.__last_number__ + 1
cls.__last_number__ = value
obj = object.__new__(cls)
obj._value_ = value
return obj
def __init__(self, *args):
"""Can handle 0 or 1 argument; more requires a custom __init__.
0 = auto-number w/o docstring
1 = auto-number w/ docstring
2+ = needs custom __init__
"""
if len(args) == 1 and isinstance(args[0], (str, unicode)):
self.__doc__ = args[0]
elif args:
raise TypeError('%s not dealt with -- need custom __init__' % (args,))
La ragione per cui mi occupo gli argomenti in __init__
anziché in __new__
è quello di rendere più facile la creazione di sottoclassi AutoEnum
dovrei voler estendere ulteriormente.
fonte
2013-10-12 04:13:49