我希望能够遍历给定类的所有基类(包括类本身)的直接和间接基类。如果您有一个元类来检查所有基类的内部Options类,那么这很有用。是否有一个标准函数来迭代基类?
要做到这一点,我写了下面:
def bases(cls):
yield cls
for direct_base in cls.__bases__:
for base in bases(direct_base):
yield base
有没有一个标准功能为我做到这一点?
我希望能够遍历给定类的所有基类(包括类本身)的直接和间接基类。如果您有一个元类来检查所有基类的内部Options类,那么这很有用。是否有一个标准函数来迭代基类?
要做到这一点,我写了下面:
def bases(cls):
yield cls
for direct_base in cls.__bases__:
for base in bases(direct_base):
yield base
有没有一个标准功能为我做到这一点?
有一种方法可以将它们全部返回,方法分辨率排序(MRO):inspect.getmro
。在这里看到:
http://docs.python.org/library/inspect.html#inspect.getmro
它返回它们作为一个元组,然后你就可以自己遍历在一个循环:
import inspect
for base_class in inspect.getmro(foo):
# do something
这有只得到每个基类,一旦附带的好处,即使你有钻石图案的继承。
我完全不知道这是否是你在找什么,但看看someclass.__mro__
,MRO是方法解析顺序
http://docs.python.org/library/stdtypes.html?highlight=mro#class.__mro__
琥珀已经为正确答案真实世界,但我会展示一个正确的方法来做到这一点。如果两个基类本身从同一个基类继承,那么您的解决方案将包含一些类两次。
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
的实现中有一个非常可读的解决方案(具有它自己的丑陋)。
谢谢。我发布后,我意识到,我可能会两次打同一班,但在我的情况下,这并不重要。 – 2010-11-04 15:16:56
这有(不可争辩的)不利用旧式课程的缺点。 'inspect.getmro'返回'cls .__ mro__'(如果它存在于新样式类中),如果不存在则执行自定义搜索。 (有趣的事实:你可以通过创建一个旧类风格的类层次结构来产生递归错误,类层次比最大递归深度更多,并调用'getmro') – aaronasterling 2010-11-04 07:56:25