如何知道父母的所有派生类?

时间:2010-02-08 06:46:38

标签: python

假设你有一个基类A,这个类由B和C重新实现。 假设还有一个类方法A.derived(),它告诉你哪些类重新实现了A,因此返回[B,C],如果你以后有class D(A): passclass D(B): pass,那么现在{{1}返回[B,C,D]。

您如何实施方法A.derived()?除非你使用元类,否则我觉得这是不可能的。您可以使用标准机制仅从子级到父级遍历继承树。要使链接处于另一个方向,您必须“手动”保留它,这意味着重写传统的类声明机制。

3 个答案:

答案 0 :(得分:18)

如果您将类定义为新样式类(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类都是一样的,因为我认为你已经知道了。

答案 1 :(得分:3)

鉴于对子类的讨论,那么实现可能如下所示:

class A(object):
    @classmethod
    def derived(cls):
        return [c.__name__ for c in cls.__subclasses__()]

修改:您可能还想查看此answer稍微不同的问题。

答案 2 :(得分: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)