如何抑制在为函数分配新属性时,mypy产生的“has no attribute”错误?

10

对于静态初始化,我经常使用以下习语:

def compute_answer() -> int:
    if compute_answer.ret is None:
        # Do stuff that only happens the first time
        compute_answer.ret = 42
    return compute_answer.ret

compute_answer.ret = None

然而,使用mypy进行类型检查会出现以下错误:

compute.py:2: error: "Callable[[], int]" has no attribute "ret"
compute.py:4: error: "Callable[[], int]" has no attribute "ret"
compute.py:5: error: "Callable[[], int]" has no attribute "ret"
compute.py:7: error: "Callable[[], int]" has no attribute "ret"

我可以翻译。请问需要翻译哪些内容?您提供的是一个HTML标签,其中只有一句话:如何抑制这些错误,特别是在本地(例如,只针对此函数/属性)?

我认为:# type: ignore - hussic
@hussic 是的,那个方法可行,但你必须在每个属性出现的行上都加上它。 - Vic
你可以使用@functools.cache装饰器吗? - Samwise
@Samwise 在这种情况下是的,但是有其他有效的原因可以将一个或多个属性存储在函数中,这些原因不会被缓存装饰器覆盖。 - Vic
1
我很好奇它们是什么 - 我实际上想不到任何你可以通过monkeypatching函数做的事情,而你不能用其他更加mypy友好(因此更加防错)和更加紧凑的方式来完成。 - Samwise
1个回答

3

您可以使用返回自定义 Protocol 的装饰器来处理函数对象。就像这样:

from typing import Any, Protocol, Optional


class ComputeAnswerProto(Protocol):
    ret: Optional[int]

    def __call__(self) -> int: ...


def compute_decorator(func: Any) -> ComputeAnswerProto:
    return func


@compute_decorator
def compute_answer() -> int:
    if compute_answer.ret is None:
        # Do stuff that only happens the first time
        compute_answer.ret = 42
    return compute_answer.ret


compute_answer.ret = None

7
目前看来,mypy并没有帮助我们编写更好、更易懂的代码,反而增加了不必要的复杂性。 - James Bradbury

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接