如何解决Mypy 抱怨默认参数值与省略号不兼容
我试图找到一种方法来区分参数是否已传递给方法。 例如,我有以下功能:
@dataclass
class Record:
id: int
name: str
completed_at: Optional[date] = None
records = [
Record(id=1,name="Foo",completed_at=date(2021,1,10)),Record(id=2,name="Bar",11)),]
def update_record(
id: int,name: Optional[str] = None,completed_at: Optional[date] = ...,# type: ignore
):
record = next(record for record in records if record.id == id)
if name is not None:
record.name = name
if completed_at is not ...:
record.completed_at = completed_at
它就像一个魅力,但当我删除 # type: ignore
评论时,mypy 抱怨以下错误:
error: Incompatible default for argument
"completed_at" (default has type "ellipsis",argument has type
"Optional[date]") [assignment]
... int,completed_at: Optional[date] = ...
我尝试了一个包含虚拟“哨兵”对象的解决方案,例如:
DO_NOTHING = object()
def update_record(id,completed_at: Union[DO_NOTHING,None,date] = DO_NOTHING):
pass
...但在我看来它有点过于冗长。
有没有办法以更简洁的方式做得更好?
解决方法
似乎来自输入模块的 @overload
正是我想要的。
完整示例:
@dataclass
class Record:
id: int
name: str
completed_at: Optional[date] = None
records = [
Record(id=1,name="Foo",completed_at=date(2021,1,10)),Record(id=2,name="Bar",11)),]
@overload
def update_record(id: int):
...
@overload
def update_record(
id: int,name: Optional[str] = None,completed_at: Optional[date] = None
):
...
def update_record(id: int,*args,**kwargs):
record = next(record for record in records if record.id == id)
for field,value in kwargs.items():
setattr(record,field,value)
def test_update():
repository = Repository(records)
repository.update(1,name="Foobar") # Do nothing with `completed_at` field
repository.update(2,completed_at=None) # Set `completed_at` to None
# repository.update(2,completed_at="2021-01-12") # Typing error
assert records == [
Record(id=1,name="Foobar",name="Bar"),]
我希望有人会觉得它有用。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。