2010-11-04 80 views
5

我希望能够遍历给定类的所有基类(包括类本身)的直接和间接基类。如果您有一个元类来检查所有基类的内部Options类,那么这很有用。是否有一个标准函数来迭代基类?

要做到这一点,我写了下面:

def bases(cls): 
    yield cls 
    for direct_base in cls.__bases__: 
     for base in bases(direct_base): 
      yield base 

有没有一个标准功能为我做到这一点?

回答

12

有一种方法可以将它们全部返回,方法分辨率排序(MRO):inspect.getmro。在这里看到:

http://docs.python.org/library/inspect.html#inspect.getmro

它返回它们作为一个元组,然后你就可以自己遍历在一个循环:

import inspect 
for base_class in inspect.getmro(foo): 
    # do something 

这有只得到每个基类,一旦附带的好处,即使你有钻石图案的继承。

0

我完全不知道这是否是你在找什么,但看看someclass.__mro__,MRO是方法解析顺序

http://docs.python.org/library/stdtypes.html?highlight=mro#class.__mro__

+1

这有(不可争辩的)不利用旧式课程的缺点。 'inspect.getmro'返回'cls .__ mro__'(如果它存在于新样式类中),如果不存在则执行自定义搜索。 (有趣的事实:你可以通过创建一个旧类风格的类层次结构来产生递归错误,类层次比最大递归深度更多,并调用'getmro') – aaronasterling 2010-11-04 07:56:25

1

琥珀已经为正确答案真实世界,但我会展示一个正确的方法来做到这一点。如果两个基类本身从同一个基类继承,那么您的解决方案将包含一些类两次。

def bases(cls): 
    classes = [cls] 
    i = 0 
    while 1: 
     try: 
      cls = classes[i] 
     except IndexError: 
      return classes 
     i += 1 
     classes[i:i] = [base for base in cls.__bases__ if base not in classes] 

唯一稍微棘手的部分是我们使用切片的地方。这是执行这种深度优先搜索而不使用递归所必需的。它所做的就是取当前正在检查的类的基类,并在它后面立即插入它们,以便第一个基类成为下一个检查的类。标准库中的inspect.getmro的实现中有一个非常可读的解决方案(具有它自己的丑陋)。

+0

谢谢。我发布后,我意识到,我可能会两次打同一班,但在我的情况下,这并不重要。 – 2010-11-04 15:16:56

相关问题