关于python:在子类化时使用(误用)super()。

Use (misuse) of super() when subclassing

在讨论如何将tkinter-FrameLabelFrame划分为子类时,我发现许多答案表明,super().__init__在划分子类时优于BaseClass.__init()__

所以我试了一下,想看看到底是怎么回事,但似乎一点效果都没有。在Python2.7中,它抱怨参数的类型。在3.4中,它表示master有多个定义。超级评论如下,它工作的预期。我做错什么了?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# import Tkinter as tki   # py 2.7
import tkinter as tki   # py 3.4

class App(tki.LabelFrame):
    def __init__(self, parent):
        tki.LabelFrame.__init__(self, master=parent, text='inner')
        # super().__init__(self, master=parent, text='inner')          #py 3.4
        # super(App, self).__init__(self, master=parent, text='inner') #py 2.7
        # super(App, self).__init__(master=parent, text='inner') #py 2.7

        self.quit = tki.Button(self, text='quit', command=exit)
        self.quit.grid()      

if __name__ == '__main__':    
    root = tki.Tk()
    root.title('nesting testing')

    outer = tki.LabelFrame(root, text='outer level')
    outer.pack()

    app = App(outer)
    app.pack()

    root.mainloop()

在对super().__init__()的调用中删除self是我尝试的第一件事情,但在py2.7中,无论它是否在那里,我仍然收到相同的错误消息。

不带self

1
2
3
4
5
6
Traceback (most recent call last):  
    File"C:\Python\TESTS\test_super.py", line 21, in <module>  
        app = App(outer)  
    File"C:\Python\TESTS\test_super.py", line 9, in __init__  
        super(App, self).__init__(master=parent, text='inner') #py 2.7  
TypeError: must be type, not classobj

使用self时:

1
2
3
4
5
6
Traceback (most recent call last):  
  File"C:\Python\TESTS\test_super.py", line 21, in <module>  
    app = App(outer)  
  File"C:\Python\TESTS\test_super.py", line 8, in __init__  
    super(App, self).__init__(self, master=parent, text='inner') #py 2.7  
TypeError: must be type, not classobj

错误消息与我删除self时保持不变的事实表明这不是问题所在,但是它与baseclass调用一起工作正常的事实使我对其他参数可能有什么问题感到困惑。


如果我记得对的话

1
2
super().__init__(self, master=parent, text='inner')          #py 3.4
super(App, self).__init__(self, master=parent, text='inner') #py 2.7

应该是-

1
2
super().__init__(master=parent, text='inner')          #py 3.4
super(App, self).__init__(master=parent, text='inner') #py 2.7

因为你不应该把self作为super的__init__的参数传递。

实际上,在使用实例方法时,不应将self显式传递给任何方法,当解释器调用时,会自动提供self

顺便说一句,

1
2
3
4
    tki.LabelFrame.__init__(self, master=parent, text='inner')
    super().__init__(self, master=parent, text='inner')          #py 3.4
    super(App, self).__init__(self, master=parent, text='inner') #py 2.7
    super(App, self).__init__(master=parent, text='inner') #py 2.7

所有这些调用都是冗余的。你应该只使用其中一个。我更喜欢-

1
    super().__init__(master=parent, text='inner')          #py 3.4

1
    super(App, self).__init__(master=parent, text='inner') #py 2.7

但是如果你喜欢用第一个-

1
    tki.LabelFrame.__init__(self, master=parent, text='inner')

一定要把自己取下来-

1
    tki.LabelFrame.__init__(master=parent, text='inner')


这样使用super时,不会显式传递self。只需对python 3执行super(App, self).__init__(master=parent, text='inner')super().__init__(master=parent, text='inner')