为什么mypy报告错误:**后面的参数必须是映射,而不是"object"



我的代码看起来像这样:

class MyClass:
k: int
v: int
def __init__(self, *, k, v):
self.k = k
self.v = v
def getkv(self):
return self.k, self.v

def test():
a = [{"k": 5, "v": 25}, {"k": 7, "v": 49}, {"k": 9, "v": 81}]
mcl = dict(MyClass(**x).getkv() for x in a)
print(a)
print(mcl)

if __name__ == "__main__":
test()

输出为:

[{'k': 5, 'v': 25}, {'k': 7, 'v': 49}, {'k': 9, 'v': 81}]
{5: 25, 7: 49, 9: 81}

在我的实际代码中,我有两个这种形式的类,其中一个mypy给出了错误:

error: Argument after ** must be a mapping, not "object"

:

mcl = dict(MyClass(**x).getkv() for x in a)

我花了一些时间编辑类,试图使它们相同,并测试差异,但我找不到任何东西,我不抱怨这个示例中的代码。

谁能告诉我为什么我可能会反对?在这两种情况下,我的测试代码产生相同的预期输出。

感谢为完整起见,下面是实际无法简化的代码:

from typing import Any, Optional
from pydantic import BaseModel, PositiveFloat, ValidationError, conint, root_validator
class UsageStat(BaseModel):
year: conint(ge=1970, le=2100)  # type: ignore
month: conint(ge=1, le=12)  # type: ignore
day: Optional[conint(ge=1, le=31)]  # type: ignore
time: conint(ge=0, le=44640)  # type: ignore
def datekv(self):
return self.day if self.is_daily else self.month, self.time

class EmeterStat(BaseModel):
year: conint(ge=1970, le=3000)  # type: ignore
month: conint(ge=1, le=12)  # type: ignore
day: Optional[conint(ge=1, le=31)]  # type: ignore
energy: PositiveFloat  # type: ignore # kW (kilo Watts)
def datekv(self, *, kwh: bool = True):
"""Return key,value pair for period index, energy."""
k = self.day if self.is_daily else self.month
v = self.energy if kwh else int(self.energy * 1000)
return k, v
# Removed some property getters
class Config:
validate_assignment = True
@root_validator(pre=True)
def _convert_energy(cls, values: dict[str, Any]) -> dict[str, Any]:
# removed code to simplify
def test():
usage_stat_list = [
{"year": 2022, "month": 9, "time": 3},
{"year": 2022, "month": 10, "time": 4},
{"year": 2022, "month": 11, "time": 5},
]
usl = dict(UsageStat(**x).datekv() for x in usage_stat_list)
emeter_stat_list = [
{"year": 2022, "month": 9, "energy": 0.3},
{"year": 2022, "month": 10, "energy_wh": 400},
{"year": 2022, "month": 11, "energy": 0.5},
]
# This is the line it complains about
usl = dict(EmeterStat(**x).datekv() for x in emeter_stat_list)

对于mypy所知道的,a可能是任何的列表。通过将其输入为字典列表来帮助它:

from typing import List
...
a: List[dict] = [{"k": 5, "v": 25}, {"k": 7, "v": 49}, {"k": 9, "v": 81}]

最新更新