python Python超类反射

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25807/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 19:24:23  来源:igfitidea点击:

Python super class reflection

pythonreflection

提问by jelovirt

If I have Python code

如果我有 Python 代码

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

and I have class C, is there a way to iterate through it's super classed (Aand B)? Something like pseudocode:

我有类C,有没有办法遍历它的超类(AB)?类似伪代码的东西:

>>> magicGetSuperClasses(C)
(<type 'A'>, <type 'B'>)

One solution seems to be inspect moduleand getclasstreefunction.

一种解决方案似乎是检查模块getclasstree功能。

def magicGetSuperClasses(cls):
    return [o[0] for o in inspect.getclasstree([cls]) if type(o[0]) == type]

but is this a "Pythonian" way to achieve the goal?

但这是实现目标的“Pythonian”方式吗?

回答by John

C.__bases__is an array of the super classes, so you could implement your hypothetical function like so:

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

def magicGetSuperClasses(cls):
  return cls.__bases__

But I imagine it would be easier to just reference cls.__bases__directly in most cases.

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

回答by cdleary

@John: Your snippet doesn't work -- you are returning the classof the base classes (which are also known as metaclasses). You really just want cls.__bases__:

@约翰:您的片段不工作-你正在返回的的基类(也被称为元类)的。你真的只想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

Also, if you're using Python 2.4+ you can use generator expressionsinstead of creating a list (via []), then turning it into a tuple (via tuple). For example:

此外,如果您使用的是 Python 2.4+,则可以使用生成器表达式而不是创建列表(通过 []),然后将其转换为元组(通过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__)

That's a somewhat confusing example, but genexps are generally easy and cool. :)

这是一个有点令人困惑的例子,但 genexps 通常既简单又酷。:)

回答by Torsten Marek

The inspect module was a good start, use the getmrofunction:

检查模块是一个好的开始,使用getmro函数:

Return a tuple of class cls's base classes, including cls, in method resolution order. No class appears more than once in this tuple. ...

按方法解析顺序返回类 cls 的基类的元组,包括 cls。在这个元组中没有类出现多次。...

>>> class A: pass
>>> class B: pass
>>> class C(A, B): pass
>>> import inspect
>>> inspect.getmro(C)[1:]
(<class __main__.A at 0x8c59f2c>, <class __main__.B at 0x8c59f5c>)

The first element of the returned tuple is C, you can just disregard it.

返回的元组的第一个元素是C,你可以忽略它。

回答by sinzi

if you need to know to order in which super() would call the classes you can use C.__mro__and don't need inspecttherefore.

如果您需要知道在哪个 super() 调用您可以使用C.__mro__但不需要的类的顺序inspect