如何在Python中表示泛型对象的扩展子类型并保留原有特性?
给对象添加属性同时保留原有类型的正确实现
你的代码问题在于,用泛型类HasFoo[T]作为返回类型时,类型检查器会只识别HasFoo的属性,丢失了原对象T的类型信息(比如函数的可调用能力)。要解决这个问题,应该用Protocol定义属性约束,再通过交类型结合原类型与约束,让类型检查器同时保留两种类型的信息。
正确代码示例
from typing import cast, TypeVar, Protocol T = TypeVar("T") # 用Protocol描述拥有foo属性的对象(无需被继承,仅做类型约束) class HasFoo(Protocol): foo: str def set_foo_on_obj(obj: T) -> T & HasFoo: setattr(obj, 'foo', 'some_value') # 类型转换为原类型T和HasFoo的交类型 return cast(T & HasFoo, obj) def func(a: int) -> int: return a func_with_foo = set_foo_on_obj(func) # 此时类型检查器会正确识别: # func_with_foo 既是接收int返回int的函数,同时拥有foo属性 func_with_foo(1) # 正常调用函数逻辑 func_with_foo.foo # 正常访问新增的foo属性
核心原理
- Protocol的作用:它是Python类型系统中用于定义“鸭子类型”的工具,只要对象具备协议中声明的属性/方法,就会被视为符合该协议,不需要显式继承。
- 交类型(T & HasFoo):表示返回的对象同时满足两个类型约束——既保留原对象
T的所有类型特性(比如函数的可调用性),又拥有HasFoo协议中定义的foo属性。这样类型检查器就能同时识别两者的信息,不会擦除原对象的类型。
内容的提问来源于stack exchange,提问作者komodovaran_
相关产品推荐
相关产品推荐

