【发布时间】:2010-11-26 23:07:59
【问题描述】:
给定一个Foo 类(无论它是否是new-style 类),如何生成所有 基类——继承层次结构中的任何位置——它的issubclass?
【问题讨论】:
标签: python class inheritance oop introspection
给定一个Foo 类(无论它是否是new-style 类),如何生成所有 基类——继承层次结构中的任何位置——它的issubclass?
【问题讨论】:
标签: python class inheritance oop introspection
你可以使用类对象的__bases__元组:
class A(object, B, C):
def __init__(self):
pass
print A.__bases__
__bases__ 返回的元组有它的所有基类。
【讨论】:
__bases__中
inspect.getclasstree() 将创建一个嵌套的类列表及其基类。
用法:
inspect.getclasstree(inspect.getmro(IOError)) # Insert your Class instead of IOError.
【讨论】:
python -c 'import inspect; from pprint import pprint as pp; pp(inspect.getclasstree(inspect.getmro(IOError)))'
查看 python class 上可用的 __bases__ property,其中包含基类的元组:
>>> def classlookup(cls):
... c = list(cls.__bases__)
... for base in c:
... c.extend(classlookup(base))
... return c
...
>>> class A: pass
...
>>> class B(A): pass
...
>>> class C(object, B): pass
...
>>> classlookup(C)
[<type 'object'>, <class __main__.B at 0x00AB7300>, <class __main__.A at 0x00A6D630>]
【讨论】:
getmro 的文档明确指出“没有类在这个元组中出现超过一次”?
__bases__ 只会上升一级。 (正如您的递归实用程序所暗示的那样,但粗略地看一下示例可能不会明白这一点。)
inspect.getmro(cls) 适用于新式和旧式类,并返回与NewClass.mro() 相同的:类及其所有祖先类的列表,按用于方法解析的顺序排列。
>>> class A(object):
>>> pass
>>>
>>> class B(A):
>>> pass
>>>
>>> import inspect
>>> inspect.getmro(B)
(<class '__main__.B'>, <class '__main__.A'>, <type 'object'>)
【讨论】:
inspect.getmro(obj) 而不是inspect.getmro(type(obj))。
虽然 Jochen 的回答非常有帮助和正确,因为您可以使用 inspect 模块的 .getmro() 方法获取类层次结构,但同样重要的是要强调 Python 的继承层次结构如下:
例如:
class MyClass(YourClass):
一个继承类
例如:
class YourClass(Object):
继承的类
一个类可以继承另一个类 - 类的属性被继承 - 特别是,它的方法是继承的 - 这意味着继承(子)类的实例可以访问继承(父)类的属性
实例 -> 类 -> 然后继承的类
使用
import inspect
inspect.getmro(MyClass)
将在 Python 中向您显示层次结构。
【讨论】:
在python 3.7中你不需要导入inspect,type.mro会给你结果。
>>> class A:
... pass
...
>>> class B(A):
... pass
...
>>> type.mro(B)
[<class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
>>>
注意,在 python 3.x 中,每个类都继承自基对象类。
【讨论】:
type.mro(my_obj) 以TypeError: descriptor 'mro' for 'type' objects doesn't apply to a 'my_obj' object 失败; type.mro(type(my_obj)) 有效。不确定这是否相关:my_obj 是 Pydantic 模型的一个实例。
根据Python doc,我们也可以简单的使用class.__mro__属性或者class.mro()方法:
>>> class A:
... pass
...
>>> class B(A):
... pass
...
>>> B.__mro__
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
>>> A.__mro__
(<class '__main__.A'>, <class 'object'>)
>>> object.__mro__
(<class 'object'>,)
>>>
>>> B.mro()
[<class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
>>> A.mro()
[<class '__main__.A'>, <class 'object'>]
>>> object.mro()
[<class 'object'>]
>>> A in B.mro()
True
【讨论】: