我想问一个关于使用 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()
现在这段代码应该做的不多了。 CCanvas类只是继承自Canvas,没有实现任何东西,只是调用父类(super class)的构造函数。我看不出任何不起作用的理由。 然而,当我运行它时,出现以下错误:
super(CCanvas,self).__init__(master=master,*args,**kwargs)
TypeError: must be type, not classobj
任何人都可以向我解释这种行为并告诉我如何解决它吗?
最佳答案
这里的问题是 TkInter 类(在 2.x 中)是旧式类。 Data Model 中详细描述了差异文档,但您不需要知道详细信息;你只需要知道you can't use super
(以及如何通过显式调用 __init__
来解决这个问题)。而且,正如 Steven Rumbalski 指出的那样,super() fails with error: TypeError “argument 1 must be type, not classobj”解释了当您尝试 super
的基类位于旧式类上时为什么会收到此错误消息。
这在文档中没有提到,除非你去寻找它,否则它并不是很明显,但如果你知道如何区分两者,就不那么难了。
正如 thread on python-list 中指出的那样,这通常不是问题,因为如果您需要新样式的类行为,您总是可以只执行 class CCanvas(tk.Canvas, object):
。
但是有几件事没有被处理,其中之一就是super
到基类的能力。相反,您必须以老式的方式做事并通过名称显式引用基类(这也意味着您必须显式传递 self
):
def __init__(self,master,*args,**kwargs):
TkInter.Canvas.__init__(self, master=master, *args, **kwargs)
(当然,另一种解决方案是已经迁移到 Python 3,那里没有旧式类……)
(为了完整起见,可以用旧式类伪造 90% 的 super
,并且在早期的 2.x 时代有一些方法流传开来……但是你不想那样做。)
关于python - 继承自 Tkinter.Canvas - 调用 super 会导致错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14389918/