如何为装饰器修饰的方法覆盖Python类型提示?
解决类型检查工具对装饰器确保非None属性的报错问题
问题背景
test_class的user属性类型标注为None | data,装饰器wrapper会在调用test方法前确保user不为None,但类型检查工具仍提示name is not a known member of None的错误,需要在不修改业务代码结构、不抑制警告的前提下解决。
解决方案
通过给装饰器添加类型注解与协议声明,让类型检查工具识别到装饰器对实例属性的保证,具体实现如下:
完整修改代码
from dataclasses import dataclass from typing import Callable, TypeVar, Protocol, cast # 定义泛型类型,绑定到test_class T = TypeVar('T', bound='test_class') # 声明协议,表示user属性非None的test_class实例 class _TestClassWithUser(Protocol): user: data def wrapper(f: Callable[[_TestClassWithUser], None]) -> Callable[[T], None]: def deco(instance: T) -> None: if not instance.user: instance.user = data(name="test") # 将实例转换为协议类型,告知类型检查工具user已非None casted_instance = cast(_TestClassWithUser, instance) return f(casted_instance) return deco @dataclass class data: name: str class test_class: def __init__(self): self.user: None | data = None @wrapper def test(self): print(self.user.name) x = test_class() x.test()
关键说明
- 协议
_TestClassWithUser:定义了一个仅包含user: data的协议,用来标记user属性确定为data类型的test_class实例。 - 装饰器类型注解:将被装饰函数的参数类型指定为
_TestClassWithUser,告诉类型检查工具:被装饰方法执行时,传入的实例满足该协议(即user非None)。 - 类型转换
cast:在装饰器内部,将处理后的实例转换为协议类型,确保类型检查工具识别到user属性的状态变化。
这种方案完全保留原有业务代码结构,无需添加警告抑制,仅通过类型系统的补充让检查工具理解装饰器的行为。
内容的提问来源于stack exchange,提问作者stef
相关产品推荐
相关产品推荐

