我正在使用Python 3.2.5。
我的代码:
class Observable:
def __init__(self):
self.observers = []
...
class View(Frame, Observable):
def __init__(self, master=None):
super().__init__(View, self)
...
堆栈追踪:
Traceback (most recent call last):
File "C:\Python34\lib\tkinter\__init__.py", line 108, in _cnfmerge
for k, v in c.items():
AttributeError: 'View' object has no attribute 'items'
你能帮我理解我做错了吗?
答案 0 :(得分:2)
您应该致电super().__init__()
。没有参数的Python 3“magic”super()
与旧super(View, self)
相当,所以你不需要将它们作为参数传递。
答案 1 :(得分:1)
通常,items()
与字典一起使用。您在items()
对象上调用了View
方法,根据您发布的代码,该方法似乎无法实现items()
。没有定义items()
方法,也没有任何子类化dict
。
另外,正如其他人已经指出的那样,对super()
的呼叫被打破了。但我认为即使你修好它也会遇到问题。
似乎View
应该从Frame
继承,因为这是创建自定义Tkinter小部件的常规方法。如果我没有弄错的话,Python的MRO将super().__init__
只调用Observable
的构造函数。这可能会打破Frame
功能。也许您应该重新考虑您的类设计,或者尝试显式调用Frame构造函数。
您还应该有一条类似
的消息_cnfmerge:后备原因:foo
请检查/发布此消息。它可能会有所帮助。
答案 2 :(得分:1)
您正在将班级View
和self
引用传递给超类__init__
构造函数。看起来你混淆了对超级构造函数的两个等价调用:
super().__init__()
super(View, self).__init__()
在这两种情况下,__init__
的参数都是适合self.__init__()
的参数。这就是您收到错误的原因。
有关如何致电super()
的详情,请参阅Python library reference for super()
。
使用super().__init__
时遇到的问题多于View
类中的一行代码,正如@AndréLaszlo注意到的那样。
根据this article about using super()
,要使用super()
进行可在子类使用多重继承时重新排序的方法调用,必须满足某些条件:
- super()调用的方法需要存在
- 调用者和被调用者需要具有匹配的参数签名
- 并且每次出现该方法都需要使用super()
第一个条件很容易;所有课程都有__init__
。第二个条件可能没问题;你所展示的所有构造函数都可以不带参数调用。
但是,您在发布的代码中打破了第三个条件:Observable.__init__()
不会在其中调用super().__init__()
。如果你真的想使用这种技术,那应该添加。 (不要忘记你可以选择不在设计中使用super()
- 你总是可以明确地调用超类构造函数。)
那么Frame.__init__()
呢?它会调用super().__init__()
吗?如果此代码不在您的控制之下,并且在其构造函数中使用super()
不“合作”,那么最安全的解决方案可能是为创建Frame
的适配器类根据that same article I linked before的“如何合并非合作班级”部分,包含super().__init__()
来电。