繁体   English   中英

将参数传递给数据类会导致 TypeError

[英]Passing the arguments to dataclass causes TypeError

尽管使用了装饰器并将参数传递给数据类,但我一直遇到数据类问题,我会收到一个TypeError说明该对象不接受任何参数。 这似乎很喜怒无常,似乎不是由代码更改触发的,对同事有用的东西对我不起作用(但有时会)。 我们都使用 Python 3.9.7 并且都使用 PyCharm 进行编码。

我从 Windows 切换到 Ubuntu 试图阻止这个问题,但大约一周后,它又发生了。 这是我最后一个堆栈跟踪错误:

Traceback (most recent call last):
  File "/home/pedro/Documents/datacollect/Python-Shape-Game/main.py", line 188, in <module>
    shapes = load_shapes()
  File "/home/pedro/Documents/datacollect/Python-Shape-Game/main.py", line 139, in load_shapes
    return [factory.create(item) for item in data["shapes"]]
  File "/home/pedro/Documents/datacollect/Python-Shape-Game/main.py", line 139, in <listcomp>
    return [factory.create(item) for item in data["shapes"]]
  File "/home/pedro/Documents/datacollect/Python-Shape-Game/factory.py", line 28, in create
    return creation_function(**arguments)
TypeError: Rectangle() takes no arguments
pygame 2.1.0 (SDL 2.0.16, Python 3.9.7)

它使用工厂/插件模式从 JSON 注册形状,factory.py 中最值得注意的行是:

shape_creation_functions: dict[str, Callable[..., Shape]] = {}
# ...
creation_function = shape_creation_functions[shape_type]
return creation_function(**arguments)

这是失败的对象:

class Shape(Protocol):
    """Represents a shape"""
    type: str
    rgb: list
    colour: tuple
    method: str
    positions: dict
    radius: int

    def map(self, position: str) -> Union[list[tuple[Any, Any]], tuple]:
        """Map the shape to the screen"""

@dataclass()
class Rectangle(Shape):
    """Represents a rectangle"""
    type: str
    rgb: list
    colour: tuple
    method: str
    positions: dict

def map(self, position: str) -> Union[list[tuple[Any, Any]], tuple]:
    """Draw the shape on the screen"""

    rect = (
        self.positions[position][0],
        self.positions[position][1],
        self.positions[position][2],
        self.positions[position][3]
    )

    return rect

我相信这是从 Python 3.8 开始对Protocol行为的更改引起的问题。 特别是,使数据类从协议继承会导致问题。

问题是,对于较新版本的 Python,从Protocol的继承将导致Rectangle在被传递给dataclass之前被分配一个__init__方法。 这是有问题的,因为dataclass不会覆盖现有方法,因此您的Rectangle类永远不会分配一个具有rgbcolour等作为参数的初始化程序。

一种解决方案是使Rectangle不继承自Shape 由于Shape不提供任何方法实现,因此这里不需要继承。 (有关结构子类型的更多详细信息,请参阅mypy 文档。)或者,如果您希望Rectangle继承自Shape ,则可以让Shape不继承自Protocol

这可能不是最相关的答案,但因为它发生在我身上,我认为它可能对其他人有帮助。

如果您使用dataclass_json中的dataclasses_json ,则注释类的顺序很重要。 所以顺序应该首先是@dataclass_json ,然后是@dataclass 否则,你会得到这个奇怪的错误,乍一看,它是完全不相关的。 我希望它有所帮助。

更新:我无法在新测试中重现我的核心结果。 我不知道这里发生了什么,请参阅下面的更新:最近的测试。 我在 codium 中使用 Python 3.8.10 进行这两个测试。 只有第二个示例仍然至少引发类似的错误。


类型错误也出现在这个简单的例子中:

from dataclasses import dataclass

@dataclass
class Point:
     x: int
     y: int

p = Point(10, 20)

出去:

TypeError: Point() takes no arguments

更新:这贯穿现在。


如果添加参数,则错误保持不变:

@dataclass
class Point(x=0,y=0):
     x: int
     y: int

p = Point(10, 20)

出去:

TypeError: Point() takes no arguments

由于未初始化属性(不在构造函数中),因此引发此错误。

更新:现在TypeError: __init_subclass__() takes no keyword arguments


要么,您逐步填写属性:

p.x = 10
p.y = 20

或者您使用以下内容。

@dataclass
class Point:
    def __init__(self, x, y):
        x: int
        y: int

p = Point(10, 20)

更新:这不会引发错误并为 p 提供Point()


效果相同,但要编写更多内容,请参阅Data Classes

@dataclass
class Point:
    def __init__(self, x:int, y:int):
        self.x = x
        self.y = y

p = Point(10, 20)

更新:这贯穿并为 p 提供Point()


我想你应该试试这样的__init__函数:

class Rectangle():
    def __init__(self, Shape):
        Shape: object

然后通过代码进一步工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM