我知道我可以输入一个类装饰器,如下所示:
T = TypeVar('T', bound=Type[Any])
def decorator(cls: T) -> T:
...
可以使用哪些:
@decorator
class Foo:
foo: int
并且对
foo
实例上的 Foo
的引用将在 mypy 中正确检查。
但是我如何输入一个返回装饰器的函数,以便被装饰的类正确输入?例如。如果参数为
decorator
,我该如何修复下面的代码
是否有与包装类的类型无关的类型?
T = TypeVar('T', bound=Type[Any])
Decorator: TypeAlias = Callable[[T], T]
def decorator(...) -> Decorator[Any]:
def wrapper(cls: T) -> T:
# some code modifying cls depending on args to "decorator"
...
return cls
return wrapper
# now instance don't type write
@decorator(...)
class Foo:
foo: int
一旦包装器类型变得足够复杂,我发现使用
typing.Protocol
会非常有用。返回的函数可以表示为非泛型类,它提供泛型 __call__
方法。
import typing as t
T = t.TypeVar('T', bound=t.Type[t.Any])
class Decorator(t.Protocol):
def __call__(self, cls: T) -> T:
...
def decorator() -> Decorator:
def wrapper(cls: T) -> T:
# some code modifying cls depending on args to "decorator"
...
return cls
return wrapper
@decorator()
class Foo:
foo: int
t.reveal_type(Foo)
t.assert_type(Foo(), Foo)
(venv) > mypy --strict main.py
main.py:25: note: Revealed type is "def () -> main.Foo"
Success: no issues found in 1 source file