Python 3.4 有一个新的 enum 模块和 Enum 数据类型。如果您还无法切换到 3.4,则 Enum 已被反向移植。
由于枚举成员支持文档字符串,就像几乎所有 python 对象一样,我想设置它们。有没有简单的方法可以做到这一点?
Python 3.4 有一个新的 enum 模块和 Enum 数据类型。如果您还无法切换到 3.4,则 Enum 已被反向移植。
由于枚举成员支持文档字符串,就像几乎所有 python 对象一样,我想设置它们。有没有简单的方法可以做到这一点?
是的,这是迄今为止我最喜欢的食谱。作为奖励,也不必指定整数值。这是一个例子:
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"
你可能会问为什么我不只是拥有"N S E W NE NW SE SW"
的价值ordinal
?因为当我看到它的 repr 时<AddressSegment.ordinal: 'N S E W NE NW SE SW'>
会有点笨拙,但是在文档字符串中随时提供这些信息是一个很好的折衷方案。
这是枚举的配方:
class AutoEnum(enum.Enum):
"""
Automatically numbers enum members starting from 1.
Includes support for a custom docstring per member.
"""
#
def __new__(cls, *args):
"""Ignores arguments (will be handled in __init__."""
value = len(cls) + 1
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,))
并在使用中:
>>> list(AddressSegment)
[<AddressSegment.ordinal: 1>, <AddressSegment.secondary: 2>, <AddressSegment.misc: 3>, <AddressSegment.street: 4>]
>>> AddressSegment.secondary
<AddressSegment.secondary: 2>
>>> AddressSegment.secondary.__doc__
'apt bldg floor etc'
我处理参数 in__init__
而不是 in的原因是如果我想进一步扩展它,可以更容易__new__
地进行子类化。AutoEnum
函数和类都有文档字符串,但大多数对象没有,甚至根本不需要它们。实例属性没有本地文档字符串语法,因为它们可以在类的文档字符串中详尽地描述,这也是我建议你做的。类的实例通常也没有自己的文档字符串,枚举成员也不过如此。
果然,您几乎可以为任何内容添加文档字符串。实际上,您确实可以将任何内容添加到几乎任何内容中,因为这就是 python 的设计方式。但它既没用也不干净,甚至@Ethan Furman 发布的内容似乎只是为了将文档字符串添加到静态属性而产生的开销。
长话短说,即使您一开始可能不喜欢它:只是不要这样做并使用枚举的文档字符串。解释其成员的含义绰绰有余。