无法识别我的错误:它似乎在调用超类构造函数的某个地方

时间:2014-12-14 21:18:23

标签: python python-3.x

我正在使用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'

你能帮我理解我做错了吗?

3 个答案:

答案 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)

您正在将班级Viewself引用传递给超类__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__()来电。