Python超级反射

jel*_*irt 31 python reflection

如果我有Python代码

class A():
    pass
class B():
    pass
class C(A, B):
    pass
Run Code Online (Sandbox Code Playgroud)

我有课C,有没有办法迭代它的超级分类(AB)?类似伪代码的东西:

>>> magicGetSuperClasses(C)
(<type 'A'>, <type 'B'>)
Run Code Online (Sandbox Code Playgroud)

一个解决方案似乎是检查模块getclasstree功能.

def magicGetSuperClasses(cls):
    return [o[0] for o in inspect.getclasstree([cls]) if type(o[0]) == type]
Run Code Online (Sandbox Code Playgroud)

但这是实现目标的"蟒蛇"方式吗?

Joh*_*ohn 36

C.__bases__ 是一个超类的数组,所以你可以像这样实现你的假设函数:

def magicGetSuperClasses(cls):
  return cls.__bases__
Run Code Online (Sandbox Code Playgroud)

但我想cls.__bases__在大多数情况下直接引用会更容易.


cdl*_*ary 11

@约翰:您的片段不行-你返回的基类(也被称为元类)的.你真的只想要cls.__bases__:

class A: pass
class B: pass
class C(A, B): pass

c = C() # Instance

assert C.__bases__ == (A, B) # Works
assert c.__class__.__bases__ == (A, B) # Works

def magicGetSuperClasses(clz):
  return tuple([base.__class__ for base in clz.__bases__])

assert magicGetSuperClasses(C) == (A, B) # Fails
Run Code Online (Sandbox Code Playgroud)

此外,如果您使用的是Python 2.4+,则可以使用生成器表达式而不是创建列表(通过[]),然后将其转换为元组(via tuple).例如:

def get_base_metaclasses(cls):
    """Returns the metaclass of all the base classes of cls."""
    return tuple(base.__class__ for base in clz.__bases__)
Run Code Online (Sandbox Code Playgroud)

这是一个有点令人困惑的例子,但genexps通常很容易和很酷.:)