使 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
好吧,使用元 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