使用 mypy 进行类型检查"now"抽象



试图将应用程序与传递时间解耦我使用了一个简单的TimeProvider抽象:

# foo.py
import datetime as dt
from typing import Protocol
class TimeProvider(Protocol):
def now(self) -> dt.datetime: ...
def myfunc(timeprovider: TimeProvider = dt.datetime):
# do stuff dependent on time
pass

class FakeTimeProvider:
def __init__(self, time: dt.datetime):
self.time = time
def now(self) -> dt.datetime:
return self.time
myfunc(dt.datetime)
myfunc(FakeTimeProvider(dt.datetime(2021, 12, 2)))

运行mypy foo.py会出现以下错误:

➜ mypy foo.py
foo.py:7: error: Incompatible default for argument "timeprovider" (default has type "Type[datetime]", argument has type "TimeProvider")
foo.py:19: error: Argument 1 to "myfunc" has incompatible type "Type[datetime]"; expected "TimeProvider"
Found 2 errors in 1 file (checked 1 source file)

你知道发生了什么事吗?TimeProvider的定义是否有问题?我不理解这个错误,因为dt.datetime有一个now方法

当您编写:def myfunc(timeprovider: TimeProvider = dt.datetime)时,您要求TimeProviderinstance,但dt.datetime是非实例类型。所以你可以做:def myfunc(timeprovider: TimeProvider = dt.datetime(1,2,3)),这对mypy来说没问题。如果你想传递一个类而不是一个实例,你必须执行:def myfunc(timeprovider: TimeProvider = Type[dt.datetime]),就像下面的代码一样:

import datetime as dt
from typing import Protocol, Type

class TimeProvider(Protocol):
def now(self) -> dt.datetime: ...

def myfunc(timeprovider: Type[TimeProvider]=dt.datetime):
# do stuff dependent on time
pass

class FakeTimeProvider:
def __init__(self, time: dt.datetime):
self.time = time
def now(self) -> dt.datetime:
return self.time

myfunc(dt.datetime)
myfunc(FakeTimeProvider)

最新更新