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

Ped*_*iro 4 python python-3.9 ubuntu-20.04

我一直遇到数据类问题,尽管使用装饰器并将参数传递给数据类,但我会得到一个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)
Run Code Online (Sandbox Code Playgroud)

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

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

这是失败的对象:

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
Run Code Online (Sandbox Code Playgroud)

小智 9

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

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


Max*_*din 5

我认为这是由于 Python 3.8 中启动行为的更改而引起的问题Protocol。特别是,让数据类继承协议会导致问题。

问题是,对于较新版本的 Python,继承 fromProtocol将导致在传递给 之前Rectangle分配一个方法。这是有问题的,因为不会覆盖现有方法,因此您的类永远不会分配具有、等作为参数的初始值设定项。__init__dataclassdataclassRectanglergbcolour

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