Python 2.x 中的super()調用需要傳送參數,Python 3.x以後可以省略

Why is super() broken in Python-2.x? – Stack Overflow.

super() is not broken — it just should not be considered the standard way of calling a method of the base class. This did not change with Python 3.x. The only thing that changed is that you don’t need to pass the arguments self, cls in the standard case that self is the first parameter of the current function and cls is the class currently being defined.

Regarding your question when to actually use super(), my answer would be: hardly ever. I personally try to avoid the kind of multiple inheritance that would make super() useful.

Edit: An example from real life that I once ran into: I had some classes defining a run() method, some of which had base classes. I used super() to call the inherited constructors — I did not think it mattered because I was using single inheritance only:

class A(object):def __init__(self, i):
        self.i = i
    def run(self, value):return self.i * value

class B(A):def __init__(self, i, j):
        super(B, self).__init__(i)
        self.j = j
    def run(self, value):return super(B, self).run(value)+ self.j

Just imagine there were several of these classes, all with individual constructor prototypes, and all with the same interface to run().

Now I wanted to add some additional functionality to all of these classes, say logging. The additional functionality required an additional method to be defined on all these classes, say info(). I did not want to invade the original classes, but rather define a second set of classes inheriting from the original ones, adding the info() method and inheriting from a mix-in providing the actual logging. Now, I could not use super() in the constructor any more, so I used direct calls:

classLogger(object):def __init__(self, name):
        self.name = name
    def run_logged(self, value):print"Running", self.name,"with info", self.info()return self.run(value)classBLogged(B,Logger):def __init__(self, i, j):
        B.__init__(self, i, j)Logger.__init__("B")def info(self):return42

Here things stop working. The super() call in the base class constructor suddenly calls Logger.__init__(), and BLogged can’t do anything about it. There is actually no way to make this work, except for removing the super() call in B itself.

[Another Edit: I don’t seem to have made my point, judging from all the comments here and below the other answers. Here is how to make this code work using super():

class A(object):def __init__(self, i,**kwargs):
        super(A, self).__init__(**kwargs)
        self.i = i
    def run(self, value):return self.i * value

class B(A):def __init__(self, j,**kwargs):
        super(B, self).__init__(**kwargs)
        self.j = j
    def run(self, value):return super(B, self).run(value)+ self.j

classLogger(object):def __init__(self, name,**kwargs):
        super(Logger,self).__init__(**kwargs)
        self.name = name
    def run_logged(self, value):print"Running", self.name,"with info", self.info()return self.run(value)classBLogged(B,Logger):def __init__(self,**kwargs):
        super(BLogged, self).__init__(name="B",**kwargs)def info(self):return42

b =BLogged(i=3, j=4)

Compare this with the use of explicit superclass calls. You decide which version you prefer.]

This and similar stories are why I think that super() should not be considered the standard way of calling methods of the base class. It does not mean super() is broken.

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 變更 )

Twitter picture

You are commenting using your Twitter account. Log Out / 變更 )

Facebook照片

You are commenting using your Facebook account. Log Out / 變更 )

Google+ photo

You are commenting using your Google+ account. Log Out / 變更 )

連結到 %s

%d 位部落客按了讚: