如何输入返回类装饰器的函数? (python3.11)

问题描述 投票:0回答:1

我知道我可以输入一个类装饰器,如下所示:

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
    
python generics python-decorators mypy
1个回答
0
投票

一旦包装器类型变得足够复杂,我发现使用

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
© www.soinside.com 2019 - 2024. All rights reserved.