super()。method()和super(self .__ class __,self).method() [英] The difference between super().method() versus super(self.__class__,self).method()

查看:985
本文介绍了super()。method()和super(self .__ class __,self).method()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我试图写的代码:

  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 )

class C(A):
def __init __(self):
print(C __init__)
super().__ init __()
super()。bind_foo()

def foo(self):
print(C foo)

b = B .foo()

c = C()
c.foo()


$ b b 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 给出

  :无参数。 

有人可以解释为什么会是这样?

解决方案

您不应该使用 self .__ class __



在Python 3中,调用 c $ c> super()无参数等同于 super(B,self) );注意类的显式命名。 Python编译器为不带参数的使用 super()的方法添加一个 __ class __ closure单元格(参见为什么是Python 3.x的super()magic?)引用了 current

如果使用 super(self .__ class__,self) super(type(self),self),当一个子类试图调用该方法时,你会遇到无限递归异常;那时 self .__ class __ 是派生类 ,而不是原始的。请参阅调用super()在派生类中,我可以传入self .__ class__?



所以,总结一下,在Python 3中:

  class B(A):
def __init __(self):
print(B __init__)
super __init __()

def foo(self):
print(B foo)
super()。foo()

等于:

  B类):
def __init __(self):
print(B __init__)
super(B,self).__ init __()

def foo :
print(B foo)
super(B,self).foo()

但你应该使用前者,因为它可以让你重复自己。



在Python 2中, / em>。



对于你的 bind_foo()方法,你必须传递一个显式类从中搜索MRO,因为Python编译器无法确定在绑定新替换 foo 时使用什么类:

  def bind_foo(self,klass = None):
old_foo = self.foo
如果klass是None:
klass = type )

def new_foo():
old_foo()
super(klass,self).foo()

self.foo = new_foo

您可以使用 __ class __ self )让Python为你提供闭包单元格,但这将引用 A ,而不是 C 这里。当您绑定新的 foo 时,您希望在MRO中搜索重写的方法,然后在 C 开始搜索。



请注意,如果您现在创建一个类 D ,则从 C ,事情会再次出错,因为现在你正在调用 bind_foo(),然后调用 super () D ,而不是 C 作为起点。最好的办法是用显式类引用调用 bind_foo()。这里 __ class __ (没有 self。)会很好:

  class C(A):
def __init __(self):
print(C __init__)
super().__ init __ b $ b self.bind_foo(__ class__)

现在你的行为与使用 super()无参数,引用当前类,您在其中定义方法 __ init __ ,传递给 super(),使得 new_foo()请注意,调用 bind_foo()方法没有意义,因为 C 。



<
super()这里;你没有在这里覆盖它,所以你可以调用 self.bind_foo()


Here is the code I was trying to write:

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

Class B and A is the expected behavior, that is, when I call b.foo(), it calls a.foo() as well with super(). Class C is the trying to mimic the child B and parent A behavior but this time I dont want to put explicitly super().foo() in the child class but I still want the parent foo() to be called. It works as expected.

However, what I dont quite get is that, under A.bind_foo, I have to use super(self.__class__,self).foo() rather than super().foo. super().foo gives a

"SystemError: super(): no arguments". 

Can someone explain why that is so?

解决方案

You should not use self.__class__ or type(self) when calling super().

In Python 3, a call to super() without arguments is equivalent to super(B, self) (within methods on class B); note the explicit naming of the class. The Python compiler adds a __class__ closure cell to methods that use super() without arguments (see Why is Python 3.x's super() magic?) that references the current class being defined.

If you use super(self.__class__, self) or super(type(self), self), you will hit an infinite recursion exception when a subclass tries to call that method; at that time self.__class__ is the derived class, not the original. See When calling super() in a derived class, can I pass in self.__class__?

So, to summarize, in Python 3:

class B(A):
    def __init__(self):
        print("B __init__")
        super().__init__()

    def foo(self):
        print("B foo")
        super().foo()

is equal to:

class B(A):
    def __init__(self):
        print("B __init__")
        super(B, self).__init__()

    def foo(self):
        print("B foo")
        super(B, self).foo()

but you should use the former, as it saves you repeating yourself.

In Python 2, you are stuck with the second form only.

For your bind_foo() method, you'll have to pass in an explicit class from which to search the MRO from, as the Python compiler cannot determine here what class is used when you bind the new replacement foo:

def bind_foo(self, klass=None):
    old_foo = self.foo
    if klass is None:
        klass = type(self)

    def new_foo():
        old_foo()
        super(klass, self).foo()

    self.foo = new_foo

You could use __class__ (no self) to have Python provide you with the closure cell, but that'd be a reference to A, not C here. When you are binding the new foo, you want the search for overridden methods in the MRO to start searching at C instead.

Note that if you now create a class D, subclassing from C, things will go wrong again, because now you are calling bind_foo() and in turn call super() with D, not C, as the starting point. Your best bet then is to call bind_foo() with an explicit class reference. Here __class__ (no self.) will do nicely:

class C(A):
    def __init__(self):
        print("C __init__")
        super().__init__()
        self.bind_foo(__class__)

Now you have the same behaviour as using super() without arguments, a reference to the current class, the one in which you are defining the method __init__, is passed to super(), making the new_foo() behave as if it was defined directly in the class definition of C.

Note that there is no point in calling bind_foo() on super() here; you didn't override it here, so you can just call self.bind_foo() instead.

这篇关于super()。method()和super(self .__ class __,self).method()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆