You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用装饰器创建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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 12:40:42