继承自Tkinter.Canvas - 调用super会导致错误

Dan*_*xan 1 python inheritance canvas tkinter super

我想问一个关于使用Canvas作为容器的聪明问题,但编写我的示例代码我偶然发现了一些奇怪的东西.这是迄今为止的代码:

import Tkinter as tk

class CCanvas(tk.Canvas):

    def __init__(self,master,*args,**kwargs):
        super(CCanvas,self).__init__(master=master,*args,**kwargs)


if __name__ == '__main__':
    root= tk.Tk()
    cc = CCanvas(root)
    cc.pack()
    root.mainloop()
Run Code Online (Sandbox Code Playgroud)

现在这段代码不应该做太多.CCanvas类继承自Canvas,没有实现任何东西,只调用超类的构造函数.我认为没有任何理由不这样做.然而,当我运行它时,我收到以下错误:

super(CCanvas,self).__init__(master=master,*args,**kwargs)
TypeError: must be type, not classobj
Run Code Online (Sandbox Code Playgroud)

任何人都可以向我解释这种行为,也许可以告诉我如何解决它?

aba*_*ert 6

这里的问题是TkInter类(在2.x中)是旧式类.数据模型文档中详细描述了这些差异,但您无需了解详细信息.你需要知道的是你不能使用super(以及如何通过显式调用来解决这个问题__init__).并且,正如Steven Rumbalski所指出的那样,super()失败并出现错误:TypeError"参数1必须是类型,而不是classobj"解释了当您尝试使用的基类super是旧类时,为什么会收到此错误消息.

文档中没有提到这一点,除非你去寻找它,否则它并不是很明显,但如果你知道如何区分这两者,那就不那么难了.

正如在python-list上的一个线程中所指出的,这通常不是问题,因为如果你需要新式的类行为,你可以随时做class CCanvas(tk.Canvas, object):.

但是有一些事情没有得到解决,其中之一就是能够进入super基类.相反,你必须以老式的方式做事,并通过名称显式引用基类(这也意味着你必须self明确传递):

def __init__(self,master,*args,**kwargs):
    TkInter.Canvas.__init__(self, master=master, *args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

(当然另一种解决方案是迁移到Python 3,没有旧式类......)

(为了完整起见,有可能假装90%的super老式课程,并且在2.x天的早期有一些食谱漂浮在后面......但你不想这样做.)