英文:
mypy complains about classmethod
问题
我有一个简单的数据类(来自pydantic)
```python
from pydantic.dataclasses import dataclass
from abc import ABCMeta
from abc import abstractmethod
@dataclass
class BaseEntity(metaclass=ABCMeta):
@classmethod
@abstractmethod
def from_dict(cls, other: dict):
...
@abstractmethod
def dict(self):
...
@dataclass
class UserEntity(BaseEntity):
id: Optional[str]
name: str
email: str
avatar: str
@classmethod
def from_dict(cls, other: dict):
return cls(
id=other.get("id"),
name=other.get("name"),
email=other.get("email"),
avatar=other.get("avatar"),
)
当我运行mypy时,我得到了一系列的错误:
>app/entities/user.py:25: error: 意外的关键字参数"id",用于"UserEntity" [call-arg]
>app/entities/user.py:25: error: 意外的关键字参数"name",用于"UserEntity" [call-arg]
>app/entities/user.py:25: error: 意外的关键字参数"email",用于"UserEntity" [call-arg]
>app/entities/user.py:25: error: 意外的关键字参数"avatar",用于"UserEntity" [call-arg]
我做错了什么?代码是正确的;它可以运行。还是这是一个mypy的bug?
$ mypy --version
mypy 1.0.0 (compiled: yes)
英文:
I have a trivial dataclass (from pydantic)
from pydantic.dataclasses import dataclass
from abc import ABCMeta
from abc import abstractmethod
@dataclass
class BaseEntity(metaclass=ABCMeta):
@classmethod
@abstractmethod
def from_dict(cls, other: dict):
...
@abstractmethod
def dict(self):
...
@dataclass
class UserEntity(BaseEntity):
id: Optional[str]
name: str
email: str
avatar: str
@classmethod
def from_dict(cls, other: dict):
return cls(
id=other.get("id"),
name=other.get("name"),
email=other.get("email"),
avatar=other.get("avatar"),
)
When I run mypy, I get this set of errors:
>app/entities/user.py:25: error: Unexpected keyword argument "id" for "UserEntity" [call-arg]
>app/entities/user.py:25: error: Unexpected keyword argument "name" for "UserEntity" [call-arg]
>app/entities/user.py:25: error: Unexpected keyword argument "email" for "UserEntity" [call-arg]
>app/entities/user.py:25: error: Unexpected keyword argument "avatar" for "UserEntity" [call-arg]
What I'm doing wrong? The code is fine; it runs. Or is it a mypy bug?
$ mypy --version
mypy 1.0.0 (compiled: yes)
答案1
得分: 2
相同的代码在标准库dataclasses模块中是可以的。
问题在于,仅凭类定义本身,无法得知UserEntity.__init__会接受任何参数,无论是位置参数还是关键字参数,因为唯一静态定义的__init__是mypy要检查的object.__init__。
然而,mypy被编写成了了解标准库中的dataclasses,特别是知道从装饰器dataclasses.dataclass可以预期会有一个__init__方法,其中有id、name等参数。
然而,这种特殊处理不适用于pydantic.dataclasses。
英文:
The same code with the standard library dataclasses module is fine.
The problem is that given the class definition alone, there is no indication that UserEntity.__init__ will accept any arguments, positional or keyword, because the only statically defined __init__ for mypy to check against is object.__init__.
However, mypy is coded to know about dataclasses from the standard library, and in particular what to expect from the decorator dataclasses.dataclass, so that it can recognize that there will be an __init__ method that has id, name, etc. as parameters.
This special treatment does not apply to pydantic.dataclasses, however.
答案2
得分: 0
你缺少了构造函数 from_dict 应该调用的部分。
def __init__(self, id, name, email, avatar):
self.id = id
self.name = name
self.email = email
self.avatar = avatar
英文:
You're missing the constructor from_dict is supposed to call.
def __init__(self, id, name, email, avatar):
self.id = id
self.name = name
self.email = email
self.avatar = avatar
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论