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)
任何人都可以向我解释这种行为,也许可以告诉我如何解决它?
这里的问题是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天的早期有一些食谱漂浮在后面......但你不想这样做.)