我的代码看起来像这样:
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}]