0

键入函数装饰器的正确方法是什么print_before,以便包装函数具有正确的类型,但我不能在不起作用的类上使用装饰器?

谢谢你

def print_before(func):
    def func_wrapper(self, *args):
        self.print_hi()
        return func(self, *args)
    return func_wrapper


class PrintThings:
    def print_hi(self):
        print("hi")

    @print_before
    def add_nums(self, a: int, b: int) -> int:
        return a + b


pt = PrintThings()
pt.add_nums(5, 4)


class ShouldNotWork:
    @print_before
    def add_nums(self, a: int, b: int) -> int:
        return a + b


snw = ShouldNotWork()
snw.add_nums(4, 5)
4

1 回答 1

1

装饰器有一个非常通用的类型。您对包装器的唯一了解是它接受至少一个未知类型的参数,并返回一些未知类型。至于装饰器本身,您只知道它返回与其参数类型相同的东西。

实际上,我们还知道一件事。不管self是什么类型,它都必须有一个print_hi方法。我们可以使用Protocol.

我们还引入了一个类型变量,它每次在 的签名中使用时都T表示同一个print_before类(或其子类) 。

from typing import Any, Tuple, Protocol, TypeVar

class PrintsHi(Protocol):
    def print_hi(self):
        pass


T = TypeVar('T', bound=PrintsHi)


def print_before(func: Callable[[T, Tuple[Any,...]], Any]) -> Callable[[T, Tuple[Any,...]], Any]:
    def func_wrapper(self: T, *args: Tuple[Any,...]):
        self.print_hi()
        return func(self, *args)
    return func_wrapper
于 2020-11-17T14:22:57.567 回答