Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使此枚举类型支持迭代?_Python - Fatal编程技术网

Python 如何使此枚举类型支持迭代?

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') >>>

在Alec Thomas的文章之后,我使用以下方法创建枚举:

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]