我正在创建一个类装饰器,但在正确输入时遇到了一些问题。下面是一个最小的可重现示例,它运行(没有运行时错误)但让 pylance(使用静态类型检查器 pyright)抱怨。
我的问题是,包装函数中的
cls
是Type[T@wrapper]
(在这个例子中实现了Type[Base]
,而不是Base
)。这会导致 cls.__init__ = init
引发 pyright 错误 cannot be assigned to member "__init__" of class "type"
.
我试图避免在整个 Decorator 定义中使用 T 而不是 Type[T],这会导致以下 pyright 错误:
Argument of type "Type[Base]" cannot be assigned to parameter of type "T@Decorator"
Type "Type[Base]" cannot be assigned to type "Base"
"Type[type]" is incompatible with "Type[Base]"
所以看起来 Decorator 期望的是 Type 而不是 Type-instance。如果这是正确的,那么问题是:如何从类装饰器访问 TypeVariable 的实例?
from typing import Any, Callable, TypeVar, Optional, Dict, Union, Generic, Type
class Base:
def __init__(self, config: str):
self.config = config
T = TypeVar('T', bound=Base)
def Decorator(arg: str) -> Callable[[Type[T]], Type[T]]:
def wrapper(cls: Type[T]) -> Type[T]:
# remember original initializer
_init = cls.__init__
# updated initializer
def init(self: T, config: str, *args, **kwargs):
_init(self, config, *args, **kwargs)
setattr(self, arg, config)
# set updated initializer
cls.__init__ = init # <-------- type missmatch
# return class with updated initializer and
return cls
return wrapper
@Decorator('test')
class Test(Base):
test: str
def task(self):
print("test module dummy task: ", self.test)
虽然代码按预期工作,但所描述的问题让我思考我是否在这里采取了正确的方法。