使用装饰器创建abstractmethod时mypy报错,如何解决?
问题:自定义抽象方法装饰器导致mypy报错
我编写了一个装饰器,可将普通方法转换为abstractmethod,代码运行符合预期,但运行mypy时出现如下错误:
mypy_try.py:20: error: Missing return statement [empty-body] mypy_try.py:20: note: If the method is meant to be abstract, use @abc.abstractmethod Found 1 error in 1 file (checked 1 source file)
我的代码如下:
import abc from functools import wraps import pytest def make_it_abstract(method_to_decorate): @wraps(method_to_decorate) def decorated_method(*method_args, **method_kwargs): return method_to_decorate(*method_args, **method_kwargs) return abc.abstractmethod(decorated_method) class MyInterfaceClass(abc.ABC): @make_it_abstract # @abc.abstractmethod def my_method(self, value: int) -> int: ... def test_abstract_method(): class MyImplementationClass(MyInterfaceClass): pass with pytest.raises( TypeError, match="Can't instantiate abstract class MyImplementationClass with abstract method my_method" ): MyImplementationClass() class MyImplementationClass(MyInterfaceClass): def my_method(self, value: int) -> float: return value +1 assert 43 == MyImplementationClass().my_method(42)
直接使用@abc.abstractmethod装饰器则无问题,请问我哪里出错了?
解答
原因
mypy是静态类型检查器,不会执行装饰器代码,仅基于装饰器的类型定义和内置规则判断方法性质。abc.abstractmethod是mypy内置识别的特殊装饰器,使用后mypy会判定该方法为抽象方法,允许用...作为空实现。
而你自定义的make_it_abstract装饰器,mypy无法识别它的作用等同于abc.abstractmethod,仍将被装饰方法当作普通方法检查。普通方法有返回类型注解但方法体仅为...,就会触发"缺少返回语句"的错误。
解决方案
方案1:给自定义装饰器添加类型注解,让mypy识别其抽象方法装饰器性质
通过类型变量和注解,告知mypy该装饰器的作用与abc.abstractmethod一致:
import abc from functools import wraps from typing import Callable, TypeVar T = TypeVar('T', bound=Callable) def make_it_abstract(method_to_decorate: T) -> T: @wraps(method_to_decorate) def decorated_method(*method_args, **method_kwargs): return method_to_decorate(*method_args, **method_kwargs) # 添加type: ignore忽略类型不匹配警告,因abc.abstractmethod返回特殊对象 return abc.abstractmethod(decorated_method) # type: ignore[return-value]
方案2:简化装饰器逻辑(无额外功能需求时)
如果装饰器仅简单包装abc.abstractmethod,无额外逻辑,可直接将其设为abc.abstractmethod的别名,mypy能直接识别:
make_it_abstract = abc.abstractmethod
修改后,mypy会正确识别被装饰方法为抽象方法,不再报错。
内容的提问来源于stack exchange,提问作者waszil
相关产品推荐
相关产品推荐

