如何在 Python 中键入用于多个子类方法的装饰器
How to type a decorator that's used for methods of multiple subclasses in Python
代码是这样的,我尝试输入g
,它是用作A
子类的方法f
的装饰器。 f
有预定义接口,所以我想避免使用 typing.Any
from typing import Callable, Type, Union
def g(func: Callable[[A], int]) -> Callable[[A], int]:
# do stuff and return a new callable.
...
class A:
def __init__(self) -> None:
self.a = 1
class B(A):
def __init__(self) -> None:
self.a = 2
@g
def f(self) -> int:
return self.a
class C(A):
def __init__(self) -> None:
self.a = 3
@g
def f(self) -> int:
return self.a
上面给出了这个错误
mypy tmp.py
tmp.py:14:6: error: Argument 1 to "g" has incompatible type "Callable[[B], int]"; expected "Callable[[A], int]"
tmp.py:23:6: error: Argument 1 to "g" has incompatible type "Callable[[C], int]"; expected "Callable[[A], int]"
Found 2 errors in 1 file (checked 1 source file)
在这种情况下,输入 g
的正确方法是什么?
TypeVar
可用于您的情况:
from typing import Callable, TypeVar
T = TypeVar('T', bound='A')
def g(func: Callable[[T], int]) -> Callable[[T], int]:
# do stuff and return a new callable.
...
class A:
def __init__(self) -> None:
self.a = 1
class B(A):
def __init__(self) -> None:
self.a = 2
@g
def f(self) -> int:
return self.a
class C(A):
def __init__(self) -> None:
self.a = 3
@g
def f(self) -> int:
return self.a
代码是这样的,我尝试输入g
,它是用作A
子类的方法f
的装饰器。 f
有预定义接口,所以我想避免使用 typing.Any
from typing import Callable, Type, Union
def g(func: Callable[[A], int]) -> Callable[[A], int]:
# do stuff and return a new callable.
...
class A:
def __init__(self) -> None:
self.a = 1
class B(A):
def __init__(self) -> None:
self.a = 2
@g
def f(self) -> int:
return self.a
class C(A):
def __init__(self) -> None:
self.a = 3
@g
def f(self) -> int:
return self.a
上面给出了这个错误
mypy tmp.py
tmp.py:14:6: error: Argument 1 to "g" has incompatible type "Callable[[B], int]"; expected "Callable[[A], int]"
tmp.py:23:6: error: Argument 1 to "g" has incompatible type "Callable[[C], int]"; expected "Callable[[A], int]"
Found 2 errors in 1 file (checked 1 source file)
在这种情况下,输入 g
的正确方法是什么?
TypeVar
可用于您的情况:
from typing import Callable, TypeVar
T = TypeVar('T', bound='A')
def g(func: Callable[[T], int]) -> Callable[[T], int]:
# do stuff and return a new callable.
...
class A:
def __init__(self) -> None:
self.a = 1
class B(A):
def __init__(self) -> None:
self.a = 2
@g
def f(self) -> int:
return self.a
class C(A):
def __init__(self) -> None:
self.a = 3
@g
def f(self) -> int:
return self.a