【问题标题】:List all base classes in a hierarchy of given class?列出给定类的层次结构中的所有基类?
【发布时间】:2010-11-26 23:07:59
【问题描述】:

给定一个Foo 类(无论它是否是new-style 类),如何生成所有 基类——继承层次结构中的任何位置——它的issubclass

【问题讨论】:

    标签: python class inheritance oop introspection


    【解决方案1】:

    你可以使用类对象的__bases__元组:

    class A(object, B, C):
        def __init__(self):
           pass
    print A.__bases__
    

    __bases__ 返回的元组有它的所有基类。

    【讨论】:

    • 如果你的类继承自一个类继承自一个类,那么只有链的第一部分会在它的__bases__
    • 简单干净,无需为单个功能导入整个模块。
    • @Temperosa 它可能简单而干净,但它是错误的
    【解决方案2】:

    inspect.getclasstree() 将创建一个嵌套的类列表及其基类。 用法:

    inspect.getclasstree(inspect.getmro(IOError)) # Insert your Class instead of IOError.
    

    【讨论】:

    • 哦,很好。要获得更好的输出,请使用 pprint! python -c 'import inspect; from pprint import pprint as pp; pp(inspect.getclasstree(inspect.getmro(IOError)))'
    【解决方案3】:

    查看 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__ 只会上升一级。 (正如您的递归实用程序所暗示的那样,但粗略地看一下示例可能不会明白这一点。)
    【解决方案4】:

    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'>)
    

    【讨论】:

    • 不适用于 pyobjc 类 :( 文件“/Users/rbp/Projects/zzzzzzz/macmdtypes.py”,第 70 行,强制打印 inspect.getmro(path) 文件“/System/ Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/inspect.py”,第 348 行,在 getmro searchbases(cls, result) 文件“/System/Library/Frameworks/Python.framework/ Versions/2.7/lib/python2.7/inspect.py",第 339 行,_searchbases for base in cls.__bases_: AttributeError: 'NSTaggedDate' object has no attribute '__bases'
    • @rbp 我怀疑你遇到了和我一样的问题:你尝试使用inspect.getmro(obj) 而不是inspect.getmro(type(obj))
    【解决方案5】:

    虽然 Jochen 的回答非常有帮助和正确,因为您可以使用 inspect 模块的 .getmro() 方法获取类层次结构,但同样重要的是要强调 Python 的继承层次结构如下:

    例如:

    class MyClass(YourClass):
    

    一个继承类

    • 儿童班
    • 派生类
    • 子类

    例如:

    class YourClass(Object):
    

    继承的类

    • 父类
    • 基类
    • 超类

    一个类可以继承另一个类 - 类的属性被继承 - 特别是,它的方法是继承的 - 这意味着继承(子)类的实例可以访问继承(父)类的属性

    实例 -> 类 -> 然后继承的类

    使用

    import inspect
    inspect.getmro(MyClass)
    

    将在 Python 中向您显示层次结构。

    【讨论】:

      【解决方案6】:

      在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 中,每个类都继承自基对象类。

      【讨论】:

      • 我的情况似乎与@esmit 对answer currently below this one 的评论相同: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 模型的一个实例。
      【解决方案7】:

      根据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
      
      

      【讨论】:

        猜你喜欢
        • 2012-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多