迭代一个类型而不实例化它

Iterate over a type without instantiating it

问题

我希望能够在不实例化类型的情况下迭代它,类似于枚举。

class Foo:
    """Class I want to iterate over without instantiating."""
    ALLOWED_VALUES = (1, 2, 3)

# I want iterating over `Foo` to be equivalent to iterating over `Foo.ALLOWED_VALUES`
for val_from_tuple, val_from_foo in zip(Foo.ALLOWED_VALUES, Foo):
    assert val_from_tuple == val_from_foo

此行为对于枚举是可能的,但前提是 ALLOWED_VALUES 是有效的 python 名称。我希望在没有此限制的情况下具有相同的迭代行为。

我试过的

我尝试将 __iter__() 作为 Foo 上的 staticmethod 实现,这样就不需要 Foo 的实例来获得 Iterator它。这允许我迭代 Foo.__iter__(),但 iter(Foo) 会引发错误。这似乎是因为 iter(Foo)type 上查找 __iter__ 方法,而不是在 Foo 上查找(因为 Foo 是一个 type 对象)。

class Foo:
    """Class I want to iterate over without instantiating."""
    ALLOWED_VALUES = (1, 2, 3)

    @staticmethod
    def __iter__():
        return Foo.ALLOWED_VALUES

# This works, but isn't what I want because it involves calling `__iter__()` explicitly.
for val in Foo.__iter__():
    print(val)

# This raises an error:
# `TypeError: 'type' object is not iterable`
for val in Foo:
    print(val)

Enum 是可迭代的,因为它使用不同的元类(EnumMeta 而不是 type)来创建它。您可以定义自己的元类来提供 __iter__ 的定义,而 type 本身没有。

class IterableClass(type):
    def __iter__(self):
        yield from self.ALLOWED_VALUES

class Foo(metaclass=IterableClass):
    ALLOWED_VALUES = (1,2,3)

for x, y in zip(Foo.ALLOWED_VALUES, Foo):
    assert x == y