我主要是c#开发人员,但我目前正在用Python开发一个项目。
我如何在Python中表示等价的Enum ?
我主要是c#开发人员,但我目前正在用Python开发一个项目。
我如何在Python中表示等价的Enum ?
当前回答
我用什么:
class Enum(object):
def __init__(self, names, separator=None):
self.names = names.split(separator)
for value, name in enumerate(self.names):
setattr(self, name.upper(), value)
def tuples(self):
return tuple(enumerate(self.names))
使用方法:
>>> state = Enum('draft published retracted')
>>> state.DRAFT
0
>>> state.RETRACTED
2
>>> state.FOO
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Enum' object has no attribute 'FOO'
>>> state.tuples()
((0, 'draft'), (1, 'published'), (2, 'retracted'))
这就给出了整数常数,比如状态。PUBLISHED和在Django模型中用作选项的二元组。
其他回答
我喜欢Java枚举,这就是我在Python中的做法:
def enum(clsdef):
class Enum(object):
__slots__=tuple([var for var in clsdef.__dict__ if isinstance((getattr(clsdef, var)), tuple) and not var.startswith('__')])
def __new__(cls, *args, **kwargs):
if not '_the_instance' in cls.__dict__:
cls._the_instance = object.__new__(cls, *args, **kwargs)
return cls._the_instance
def __init__(self):
clsdef.values=lambda cls, e=Enum: e.values()
clsdef.valueOf=lambda cls, n, e=self: e.valueOf(n)
for ordinal, key in enumerate(self.__class__.__slots__):
args=getattr(clsdef, key)
instance=clsdef(*args)
instance._name=key
instance._ordinal=ordinal
setattr(self, key, instance)
@classmethod
def values(cls):
if not hasattr(cls, '_values'):
cls._values=[getattr(cls, name) for name in cls.__slots__]
return cls._values
def valueOf(self, name):
return getattr(self, name)
def __repr__(self):
return ''.join(['<class Enum (', clsdef.__name__, ') at ', str(hex(id(self))), '>'])
return Enum()
示例使用:
i=2
@enum
class Test(object):
A=("a",1)
B=("b",)
C=("c",2)
D=tuple()
E=("e",3)
while True:
try:
F, G, H, I, J, K, L, M, N, O=[tuple() for _ in range(i)]
break;
except ValueError:
i+=1
def __init__(self, name="default", aparam=0):
self.name=name
self.avalue=aparam
所有类变量都定义为元组,就像构造函数一样。到目前为止,还不能使用命名参数。
Davidg建议使用词典。我想更进一步,使用集合:
months = set('January', 'February', ..., 'December')
现在你可以测试一个值是否与集合中的一个值匹配,如下所示:
if m in months:
但是,像dF,我通常只使用字符串常量来代替枚举。
嗯…我认为最接近枚举的应该是字典,定义如下:
months = {
'January': 1,
'February': 2,
...
}
or
months = dict(
January=1,
February=2,
...
)
然后,你可以像这样使用常量的符号名:
mymonth = months['January']
还有其他选项,如元组列表或元组的元组,但字典是唯一提供“符号”(常量字符串)方式来访问 价值。
编辑:我也喜欢亚历山大的答案!
def enum( *names ):
'''
Makes enum.
Usage:
E = enum( 'YOUR', 'KEYS', 'HERE' )
print( E.HERE )
'''
class Enum():
pass
for index, name in enumerate( names ):
setattr( Enum, name, index )
return Enum
虽然最初的全会提案PEP 354在几年前被否决,但它不断被提出。本打算将某种enum添加到3.2,但它被推回到3.3,然后被遗忘。现在有一个PEP 435打算包含在Python 3.4中。PEP 435的参考实现是flufl.enum。
截至2013年4月,似乎有一个普遍的共识,即应该在3.4的标准库中添加一些东西——只要人们能够就“一些东西”应该是什么达成一致。这是最难的部分。看看从这里和这里开始的线程,以及2013年初的六个其他线程。
与此同时,每次出现这个问题时,PyPI、ActiveState等上都会出现大量的新设计和实现,所以如果你不喜欢FLUFL设计,可以尝试一下PyPI搜索。