在类的方法中,我需要调用定义方法的类的super(),而不是对象的类。我特别关心Python 2.x,但欢迎使用3.x解决方案。
我想拥有可以在整个项目中使用的通用样板文件,其中一个类从另一个类继承到未知深度。为了避免递归错误,我需要调用定义代码的当前类的父类,而不是self
对象的父类。每个模块中有许多地方引用了当前的类名,因为扩展了许多方法,每个扩展方法都可以调用父类方法。
这里的演示失败了:
#!/usr/bin/env python
from inspect import stack
class Foo(object):
def __init__(self):
print "Foo.__init__()"
print "file: %s" % __file__
print "class: %s" % self.__class__.__name__
print "stack: %s" % stack()[0][3]
print
class Bar(Foo):
def __init__(self):
print "Bar.__init__()"
super(type(self), self).__init__()
class Baz(Bar):
pass
foo = Foo()
bar = Bar()
baz = Baz()
结果如下:
Foo.__init__()
file: ./class.py
class: Foo
stack: __init__
Bar.__init__()
Foo.__init__()
file: ./class.py
class: Bar
stack: __init__
Bar.__init__()
Bar.__init__()
# snip several hundred lines
Bar.__init__()
Bar.__init__()
Traceback (most recent call last):
File "./class.py", line 24, in <module>
baz = Baz()
File "./class.py", line 16, in __init__
super(type(self), self).__init__()
# snip several hundred lines
File "./class.py", line 16, in __init__
super(type(self), self).__init__()
File "./class.py", line 16, in __init__
super(type(self), self).__init__()
RuntimeError: maximum recursion depth exceeded while calling a Python object
答案 0 :(得分:1)
正如您已经发现,使用type(self)
会导致递归,因为Baz.__init__
会定向到Bar.__init__
,但在那里您想再次呼叫super(Baz, self).__init__
Bar.__init__
所以你最终会得到一个无限递归。
通常情况下,您只会在不知道您称之为哪个类实例的情况下调用父级,因为否则您需要真正了解并修复MRO
。您始终可以使用self.__class__
或self.__class__.__name__
解决问题非常简单:将super
- 来电替换为:
super(Bar, self).__init__()
在python3中避免这些(大多数是不必要的)类的超级硬编码也可以使用:
super().__init__()
这将始终在实现它的 next 父类上调用该方法。很少有情况下当前类的父类不是超级调用解析的下一个父类。
然后输出变为(缺少__file__
):
Foo.__init__()
class: Foo
stack: __init__
Bar.__init__()
Foo.__init__()
class: Bar
stack: __init__
Bar.__init__()
Foo.__init__()
class: Baz
stack: __init__