Python 如何使此枚举类型支持迭代?
在Alec Thomas的文章之后,我使用以下方法创建枚举:Python 如何使此枚举类型支持迭代?,python,Python,在Alec Thomas的文章之后,我使用以下方法创建枚举: def enum(*sequential): enums = dict(zip(sequential, range(len(sequential)))) return type('Enum', (), enums) 我希望能够获得其中一个枚举的长度。例如,我会写作 >>> Suit = enum('spades', 'hearts', 'diamonds', 'clubs') >>>
def enum(*sequential):
enums = dict(zip(sequential, range(len(sequential))))
return type('Enum', (), enums)
我希望能够获得其中一个枚举的长度。例如,我会写作
>>> Suit = enum('spades', 'hearts', 'diamonds', 'clubs')
>>> Suit.spades
0
>>> Suit.hearts
1
>>> Suit.diamonds
2
>>> Suit.clubs
3
但无法在运行时列出所有枚举值。我希望能做一些类似的事情
>>> [s for s in Suit]
[0, 1, 2, 3]
我已尝试在enum()
函数中分配enum[''''\uu iter\u']
,但我不知道需要分配什么类型的对象:
def enum(*sequential):
enums = dict(zip(sequential, range(len(sequential))))
enums['__iter__'] = iter(range(len(sequential)))
return type('Enum', (), enums)
给予
>>[s代表穿西装的人]
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:“type”对象不可编辑
如何使
enum
能够列出其成员?(即使只是enum报告其长度的功能也足够了,因为成员只是范围(len(Suit))
的元素)我建议您使用不同的枚举器实现
实施
>>> from collections import namedtuple
>>> def enum(*sequential):
enums = namedtuple('enums',sequential)(*range(len(sequential)))
return enums
用法
>>> Suit = enum('spades', 'hearts', 'diamonds', 'clubs')
>>> Suit.spades
0
>>> Suit.hearts
1
>>> Suit.diamonds
2
>>> Suit.clubs
3
>>> [s for s in Suit]
[0, 1, 2, 3]
问题是type(…)
返回一个类型,即实际用于创建对象的内容。当然,现在您可以争论这是否是一个问题,这可能不是因为Python的类型系统如何工作(一切都是一个对象,类型只是类型的对象
对象等)
但是,这样做的效果是,您不能添加特殊的方法,就像在本例中需要的那样。但是,特殊方法是在对象的类型上查找的,因此在本例中是在类型上查找的(这是您正在创建的类型的基本类型)。而类型
——正如您所期望的那样是不可接受的
所以,如果你想拥有可移植的东西,你需要创建一些非类型的东西。您可能会在这里想出一些奇特的元类,但是您可以做的最简单的事情,也就是保持代码的长度不变,实际上是一个。顺便说一句,这也是Python 3.4中的语义的灵感来源
>>> def enum(*keys):
return namedtuple('Enum', keys)(*range(len(keys)))
>>> Suit = enum('spades', 'hearts', 'diamonds', 'clubs')
>>> Suit.spades
0
>>> Suit.hearts
1
>>> Suit.diamonds
2
>>> Suit.clubs
3
>>> [s for s in Suit]
[0, 1, 2, 3]
你的变种有效!在之后添加()
,键入(…)
以创建类实例并修改\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
def enum(*sequential):
enums = dict(zip(sequential, range(len(sequential))))
enums['__iter__'] = lambda e,i=iter(range(len(sequential))): i
return type('Enum', (object,), enums)()
>>> suit = enum('spades', 'hearts', 'diamonds', 'clubs')
>>> [s for s in suit]
[0, 1, 2, 3]
这似乎符合您的要求:
def enum(*sequential):
length = len(sequential)
pairs = zip(sequential, xrange(len(sequential)))
Enum = type('Enum', (), dict(pairs))
Enum.__len__ = lambda _: length
Enum.__iter__ = lambda _: iter(range(length))
return Enum()
Suit = enum('spades', 'hearts', 'diamonds', 'clubs')
print Suit.spades # 0
print Suit.hearts # 1
print Suit.diamonds # 2
print Suit.clubs # 3
print 'len(Suit):', len(Suit) # len(Suit): 4
print [s for s in Suit] # [0, 1, 2, 3]
@JoelCornett你不能在\uuuuuuuuuu iter\uuuuuuuuuuuu
中进行修补,请看我的答案。@poke:>。<当然。但是,您可以实例化和迭代。如列表(Suit())
所示。如果您已经修补了\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuiuuuuuuuuuuuuuuuuuuuuuuu。
def enum(*sequential):
length = len(sequential)
pairs = zip(sequential, xrange(len(sequential)))
Enum = type('Enum', (), dict(pairs))
Enum.__len__ = lambda _: length
Enum.__iter__ = lambda _: iter(range(length))
return Enum()
Suit = enum('spades', 'hearts', 'diamonds', 'clubs')
print Suit.spades # 0
print Suit.hearts # 1
print Suit.diamonds # 2
print Suit.clubs # 3
print 'len(Suit):', len(Suit) # len(Suit): 4
print [s for s in Suit] # [0, 1, 2, 3]