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

如何在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属性

核心原理

  1. Protocol的作用:它是Python类型系统中用于定义“鸭子类型”的工具,只要对象具备协议中声明的属性/方法,就会被视为符合该协议,不需要显式继承。
  2. 交类型(T & HasFoo):表示返回的对象同时满足两个类型约束——既保留原对象T的所有类型特性(比如函数的可调用性),又拥有HasFoo协议中定义的foo属性。这样类型检查器就能同时识别两者的信息,不会擦除原对象的类型。

内容的提问来源于stack exchange,提问作者komodovaran_

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 19:40:32