【问题标题】:Python,Kivy - How to debug TypeError: object.__init__() takes exactly one argument?Python,Kivy - 如何调试 TypeError:object.__init__() 只采用一个参数?
【发布时间】:2020-05-12 13:47:04
【问题描述】:

我已经使用 Kivy 的 EventDispatcher 类和 mongodb 实现了 DAO

我的代码结构如下:

class Meta(type):

    # meta deffinition

    @property
    def objects():
        #returns a db connection instance, for queries


class Model(EventDispatcher, metaclass=Meta)

    # model deffinition

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs) # this is the line that causes my problem

我有很多模型都是用这种结构定义的:

class FooModel(Model):

    # foo definition


class BarModel(Model):

    # bar deffinition


class PsyModel(FooModel):

    # psy deffinition


class XPTOModel(BarModel):

    # psy deffinition

...

模型定义只添加属性、getter 和 setter

隔离,模型实例化工作正常,所有预期行为都正常

但在尝试实例化模型时,我在堆栈跟踪深处的特定部分收到以下错误:

   File "/path/to/project/models.py", line 83, in __init__
     super().__init__(*args, **kwargs)
   File "kivy/_event.pyx", line 243, in kivy._event.EventDispatcher.__init__
 TypeError: object.__init__() takes exactly one argument (the instance to initialize)

我的代码中的所有模型都使用相同的方法调用进行实例化,但此错误仅存在于特定场景中,我很难跟踪问题。 我使用调试工具检查了对象、它的类型和 MRO,但它们遵循相同的、期望的结构。

MRO:

(<class 'models.PsyModel'>, <class 'models.FooModel'>, <class 'models.Model'>, <class 'kivy._event.EventDispatcher'>, <class 'kivy._event.ObjectWithUid'>, <class 'object'>)
(<class 'models.XPTOModel'>, <class 'models.BarModel'>, <class 'models.Model'>, <class 'kivy._event.EventDispatcher'>, <class 'kivy._event.ObjectWithUid'>, <class 'object'>)

所以我想知道这可能是什么原因造成的?以及如何进一步了解可能发生的情况?

【问题讨论】:

  • 如果oyu不做元类的事情会发生这种情况吗?
  • 我不知道。我必须重构很多代码来测试它。我的大部分 DAO 实现都依赖于此。但就像我说的那样,即使在那里,在许多其他情况下,代码工作得很好。我对这个错误的一般运行时原因更感兴趣
  • 正如我想象的那样,这是最愚蠢的情况,我确实向 init 传递了更多参数。我会解释我的答案

标签: python kivy typeerror dao method-resolution-order


【解决方案1】:

tl;dr:事实证明,我确实在 MRO 中传递了更多参数,直到达到 object.__init__,因为我的 kwargs 的参数与 MRO 类中的任何 kivy 属性都不匹配。

所以.. 使用 kwargs 实例化 Kivy 的小部件或任何 EventDispatcher 子类时,如下所示:

class MyClass(EventDispatcher):

    prop = StringProperty()

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

obj = MyClass(prop='will consume', not_a_prop='will not consume')

kivy 的属性处理使用与当前类的 kivy 属性匹配的 kwarg,但只使用匹配的那些,并允许其余的继续到 MRO 中的下一个类,最终达到object

在上面的例子中,当实例化MyClass时,prop会被MyClass.__init__消耗掉,但是由于MRO中没有一个类有一个名为not_a_prop的kivy属性,它会被传递到下一个class'__init__ 调用,最终到达object.__init__

【讨论】:

    猜你喜欢
    • 2019-10-17
    • 2012-06-26
    • 1970-01-01
    • 2021-07-11
    • 2021-09-15
    • 1970-01-01
    • 2021-12-19
    • 2021-01-29
    • 2020-01-25
    相关资源
    最近更新 更多