如何为__get__方法添加注解,使类型检查器识别新增类成员?
问题描述
想要实现一个装饰器,为被装饰类的实例添加外部类的成员属性。示例中,装饰器memberclass会给类y的实例添加一个类型为X的self属性。目前需要为装饰器的__get__方法添加类型注解,让类型检查器能识别“Y类实例会新增一个类型为X的self成员”,但未找到可行方案。
示例代码
class memberclass[Y]: def __init__(self, cls: type[Y]): self.cls = cls def __get__(self, x, cls) -> Y | type[Y]: if x is None: return self.cls # 省略按X实例缓存y的相关代码 y = self.cls() y.self = x return y class X: z: int @memberclass class y: def f(self): # self.self是X的实例 # 希望类型检查器能识别self.self.z
解决方案
可以通过**泛型协议(Generic Protocol)**来描述被装饰类实例增强后的类型,让类型检查器识别新增的属性:
步骤1:定义泛型协议
引入必要的类型工具,定义一个协议来表示带有外部类实例属性的类型:
from typing import Generic, TypeVar, Protocol # 定义类型变量,T代表外部类(如X)的类型,Y代表被装饰类(如y)的类型 T = TypeVar('T') Y = TypeVar('Y') # 协议:表示拥有一个类型为T的self属性的对象 class WithOuterSelf(Protocol[T]): self: T
步骤2:修改装饰器的类型注解
调整memberclass为泛型类,在__get__方法中用协议替代原有的返回类型:
class memberclass(Generic[Y, T]): def __init__(self, cls: type[Y]): self.cls = cls def __get__(self, x: T, cls) -> WithOuterSelf[T] | type[Y]: if x is None: return self.cls # 省略缓存逻辑 y = self.cls() y.self = x return y
步骤3:验证类型检查
修改后的代码中,类型检查器会自动识别X.y实例的self.self属性:
class X: z: int @memberclass class y: def f(self): # 类型检查器可识别self.self是X实例,self.self.z是int类型 print(self.self.z)
原理说明
- 泛型协议
WithOuterSelf[T]明确声明了“拥有类型为T的self属性”这一约束; - 装饰器
__get__方法返回该协议类型,告诉类型检查器:返回的Y类实例不仅具备原有的属性方法,还额外拥有一个self属性; - 类型检查器会据此推断
self.self的类型为外部类X的实例,从而正确识别self.self.z的类型。
内容的提问来源于stack exchange,提问作者Superior
相关产品推荐
相关产品推荐

