这是我想写的代码:
class A(object):
def bind_foo(self):
old_foo = self.foo
def new_foo():
old_foo()
#super().foo()
super(self.__class__,self).foo()
self.foo = new_foo
def __init__(self):
print("A __init__")
def foo(self):
print("A foo")
class B(A):
def __init__(self):
print("B __init__")
super().__init__()
def foo(self):
print("B foo")
super().foo()
class C(A):
def __init__(self):
print("C __init__")
super().__init__()
super().bind_foo()
def foo(self):
print("C foo")
b = B()
b.foo()
c = C()
c.foo()
类B和类A是预期的行为,也就是说,当我调用b.foo()
时,它调用a.foo()
以及super()
。类C试图模拟子B和父A的行为,但这次我不想显式地将super().foo()
放在子类中,但我仍然希望调用父foo()
。它按预期工作。
然而,我不太明白的是,在A.bind_foo
下,我必须使用super(self.__class__,self).foo()
,而不是super().foo
。super().foo
给出
"SystemError: super(): no arguments".
有人能解释为什么吗?
调用
super()
时,不应使用self.__class__
或type(self)
。在Python 3中,对
super()
的无参数调用相当于super(B, self)
(在类B
的方法内);注意类的显式命名。Python编译器将一个__class__
闭包单元添加到使用super()
的方法中,这些方法没有引用正在定义的当前类的参数(请参见Why is Python 3.x's super() magic?)。如果使用
super(self.__class__, self)
或super(type(self), self)
,则当子类尝试调用该方法时,将遇到无限递归异常;此时self.__class__
是派生类而不是原始类。见When calling super() in a derived class, can I pass in self.__class__?总之,在Python 3中:
等于:
但你应该使用前者,因为它可以省去你重复的时间。
在Python 2中,您只能使用第二种形式来。
对于您的
bind_foo()
方法,您必须传入一个显式类,从中搜索MRO,因为Python编译器无法在这里确定绑定新替换项时使用的类foo
:您可以使用
__class__
(noself
)让Python为您提供闭包单元,但这是对A
的引用,而不是这里的C
。当绑定新的foo
时,您希望在MRO中搜索重写的方法开始在C
进行搜索。请注意,如果您现在创建一个类
D
,从C
创建子类,那么就会再次出现问题,因为现在您正在调用bind_foo()
,并以D
而不是C
作为起点依次调用super()
。那么,最好的方法是用一个显式的类引用调用bind_foo()
。这里__class__
(不self.
)会做得很好:现在,您的行为与使用不带参数的
super()
相同,对当前类的引用(在该类中定义方法__init__
)被传递给super()
,使new_foo()
的行为如同它是在C
的类定义中直接定义的一样。注意,在这里调用
super()
上的bind_foo()
是没有意义的;您没有在这里重写它,所以您可以只调用self.bind_foo()
。相关问题 更多 >
编程相关推荐