使用mypy对TimeProvider时间抽象做类型检查时报错如何解决?
问题原因
你定义的TimeProvider协议中now被声明为实例方法,要求入参是「带有now实例方法的对象」。而你传入的dt.datetime是类对象,它的now方法属于类方法,不符合实例方法的匹配规则,因此mypy抛出类型不兼容错误。
解决方案
有两种常用的修复方案:
方案1:调整Protocol定义兼容类方法场景
给协议中的now方法添加@classmethod装饰器,修改后的协议可以同时匹配「带now类方法的类」和「带now实例方法的实例」两类场景,原有业务代码无需改动:
class TimeProvider(Protocol): @classmethod def now(cls) -> dt.datetime: ...
修改后重新执行mypy foo.py即可消除报错。
方案2:使用系统时间的实例包装类作为默认值
新增一个返回当前系统时间的实现类,用它的实例作为入参默认值,无需修改原有协议定义,语义更清晰:
# 新增系统时间实现类 class SystemTimeProvider: def now(self) -> dt.datetime: return dt.datetime.now() # 修改默认值为SystemTimeProvider的实例 def myfunc(timeprovider: TimeProvider = SystemTimeProvider()): # 执行依赖时间的业务逻辑 pass
修改后调用myfunc()默认会使用系统时间,测试时仍可传入FakeTimeProvider的实例做时间Mock。
内容的提问来源于stack exchange,提问作者Sebastián Bevc
相关产品推荐
相关产品推荐

