Ja, es ist, und es ist mein Lieblingsrezept bisher. Als Bonus muss man auch keinen ganzzahligen Wert angeben. Hier ein Beispiel:
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"
Sie fragen sich vielleicht, warum ich einfach nicht "N S E W NE NW SE SW"
haben kann der Wert von ordinal
? Weil, wenn ich seine repr sehene <AddressSegment.ordinal: 'N S E W NE NW SE SW'>
bekomme ein bisschen klobig, aber diese Informationen leicht verfügbar in der Docstring ist ein guter Kompromiss.
Hier ist das Rezept für die 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,))
Der Grund, warum ich in __new__
die Argumente in __init__
statt handhaben ist, um Subklassifizieren AutoEnum
leichter soll ich es weiter ausbauen will.