You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为__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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 15:36:05