如何知道某个父类的所有派生类?
假设你有一个基础类A,这个类被B和C重新实现了。还有一个类方法A.derived()
,它可以告诉你哪些类在重新实现A,所以它会返回[B, C]。如果你后来又定义了class D(A): pass
或者class D(B): pass
,那么现在A.derived()
会返回[B, C, D]。
那么,你该怎么实现这个方法A.derived()
呢?我觉得这可能不太容易,除非你使用元类。因为用标准的方法,你只能从子类向父类遍历继承树。如果想要反向链接,也就是从父类找到子类,你就得手动维护这个关系,这就意味着你需要改变传统的类声明方式。
3 个回答
2
这里有另一个实现方法,它会递归地打印出所有的子类,并且会加上缩进。
def findsubclass(baseclass, indent=0): if indent == 0: print "Subclasses of %s are:" % baseclass.__name__ indent = indent + 1 for c in baseclass.__subclasses__(): print "-"*indent*4 + ">" + c.__name__ findsubclass(c, indent)
3
根据关于子类的讨论,下面的实现可能是这样的:
class A(object):
@classmethod
def derived(cls):
return [c.__name__ for c in cls.__subclasses__()]
补充说明: 你可能还想看看这个 回答,它是针对一个稍微不同的问题。
23
如果你把你的类定义为新式类(也就是继承自 object
的类),那么就可以做到这一点,因为子类会被保存在 __subclasses__
里。
class A(object):
def hello(self):
print "Hello A"
class B(A):
def hello(self):
print "Hello B"
>>> for cls in A.__subclasses__():
... print cls.__name__
...
B
我不太清楚这个功能具体是什么时候引入的,或者有没有什么特别的注意事项。不过,在一个函数里声明一个子类是完全没问题的:
>>> def f(x):
... class C(A):
... def hello(self):
... print "Hello C"
... c = C()
... c.hello()
... print x
... for cls in A.__subclasses__():
... print cls.__name__
...
>>> f(4)
Hello C
4
B
C
不过,你需要注意的是,在类的定义被执行之前,解释器是不会知道这些类的。在上面的例子中,C
直到函数 f
被执行后,才会被识别为 A 的子类。但这对于 Python 的类来说,每次都是这样,我想你应该已经知道了。