Правильная типизация для декоратора функций класса
Как правильно набрать
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)
2 ответа
Как написано, декоратор имеет очень общий тип. Единственное, что вы знаете об оболочке, это то, что она принимает хотя бы один аргумент неизвестного типа и возвращает какой-то неизвестный тип. Что касается самого декоратора, вы знаете только, что он возвращает что-то того же типа, что и его аргумент.
Собственно, мы знаем еще кое-что. Независимо от типа
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
Я бы посмотрел на typing.Callable для набора функций. Или для классов / объектов typing.Protocol.