【问题标题】:Use (misuse) of super() when subclassing子类化时使用(误用)super()
【发布时间】:2014-07-07 22:03:24
【问题描述】:

在努力解决如何将 tkinter FrameLabelFrame 子类化以便他们坐在正确的父类上时,我发现很多答案表明 super().__init__ 在子类化时优于 BaseClass.__init()__

所以我试了一下,看看有什么大惊小怪的,它似乎根本不起作用。在 python 2.7 中,它抱怨参数的类型。在 3.4 中,它说 master 有多个定义。将 super 注释如下,它按预期工作。我做错了什么?

# 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

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:

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 调用中正常工作的事实让我对其他参数可能有什么问题感到困惑。

【问题讨论】:

  • 总结来自@Veedrac 的非常有用的链接:您不能在Python 2.7 中将super 与该类一起使用,因为它是一个“旧样式”类(它不继承自object )。在 Python 3 中,所有类都是“新样式”,因此 super 可以工作(包括新的无参数版本)。

标签: python tkinter class-hierarchy


【解决方案1】:

如果我没记错的话

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

应该是——

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在解释器调用时会自动提供

顺便说一句,

    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

所有这些调用都是多余的。您应该只使用其中之一。我更喜欢 -

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

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

但如果您更喜欢使用第一个 -

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

确保你删除自我并成功 -

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

【讨论】:

  • 我已经编辑了问题以显示该测试的结果,我一定是做错了什么?
  • 更新了我的答案,请检查。
  • 如果我在没有 self 的情况下尝试 super(),它会告诉我缺少位置参数 self,至少在 3.4 中是这样。也许我应该停止打击 tkinter 类,它们的行为似乎不像它们应该的那样,而只使用有效的。
【解决方案2】:

以这种方式使用super 时,您不会显式传递self。只需执行super(App, self).__init__(master=parent, text='inner')(或super().__init__(master=parent, text='inner') 用于Python 3)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-12
    • 1970-01-01
    • 1970-01-01
    • 2018-06-23
    • 2015-07-22
    • 2012-08-08
    • 1970-01-01
    • 2016-10-12
    相关资源
    最近更新 更多