使 class 在继承方面可迭代

Make class iterable respecting inheritance

好吧,使用元 classes 简单地使 class 可迭代就足够容易了(所以这里有一些其他的答案)。但是,我希望使 class 可迭代,并使一个 "iterate a subgroup based on inheritance" 成为可迭代的。我的使用示例:

class IterPartRegistry(type):
    def __iter__(cls):
        return iter(cls._registry)


class A(object, metaclass=IterPartRegistry):
    _registry = []
    def __init__(self, name):
        self.name = name
        self._registry.append(self)

class B(A):
    pass

class C(A):
    pass


A("A - first")
B("B - first")
B("B - second")
C("C - first")

for t in A:
    print(t.name)

print(" --- ")
for t in B:
    print(t.name)

exit()

第一个循环有效 - 它遍历所有实例和 "A" 的 childs。然而,第二个循环应该只 运行 在 "A" 的特定子组上 - 那些是 child "B" 的实例(或 children 进一步向下).

(如何)最容易做到这一点?以这种方式添加更多子 classes 需要最少的 work/change?

您可以使用 isinstance 来确保您只获得 class 个实例

在您的代码中,只需更改一行:

class IterPartRegistry(type):
    def __iter__(cls):
        return (c for c in cls._registry if isinstance(c, cls))

您可以让每个 class 通过给每个 class 维护自己的实例列表 它自己的 _registry class 属性。然后,而不是检查每个 实例属于特定 class,您可以为 cls 的每个子 class 遍历 _registry 中的所有值。要找到那些 subclasses 你可以使用 cls.__subclasses__()方法:

import itertools as IT
class IterPartRegistry(type):
    def __init__(cls, name, bases, attrs):
        super(IterPartRegistry, cls).__init__(name, bases, attrs)
        cls._registry = []
    def __iter__(cls):
        yield from cls._registry
        for subcls in cls.__subclasses__():
            yield from subcls

class A(object, metaclass=IterPartRegistry):
    def __init__(self, name):
        self.name = name
        self._registry.append(self)

class B(A): pass

class C(A): pass

class D(B, C): pass

A("A - first")
B("B - first")
B("B - second")
C("C - first")
D("D - first")

for t in A:
    print(t.name)

print(" --- ")
for t in B:
    print(t.name)

产量

A - first
B - first
B - second
D - first
C - first
D - first
 --- 
B - first
B - second
D - first