Tak, jest i jest to mój ulubiony przepis do tej pory. Jako bonus nie trzeba również podawać liczby całkowitej. Oto przykład:
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"
Można zapytać, dlaczego nie wystarczy mieć "N S E W NE NW SE SW"
być wartość ordinal
? Ponieważ kiedy dostaję jego repr widząc, że <AddressSegment.ordinal: 'N S E W NE NW SE SW'>
staje się nieco niezdarny, ale posiadanie tych informacji łatwo dostępnych w docstrukcji jest dobrym kompromisem.
Oto przepis na 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,))
Powodem obsługiwać argumenty w __init__
zamiast w __new__
jest, aby subclassing AutoEnum
łatwiej powinno Chcę rozszerzyć dalej.