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

如何为Python函数返回值标注实例而非类型以实现类型收窄?

如何标注函数返回单例实例以支持类型收窄?

你可以通过以下方式实现需求,无需额外TypeGuard代码,保留is语句的类型收窄能力:

一、字符串单例场景

先使用Final标记单例变量为不可变,再结合Literal标注返回类型,类型检查器会识别is判断并收窄类型:

from typing import Final, Literal, Union

my_marker: Final[str] = "This is very singletony, I promise!"

def get_object_or_a_singleton_marker() -> Union[int, Literal[my_marker]]:
    some_condition_is_met = False  # 示例条件
    if some_condition_is_met:
        return 123  # 示例int返回值
    else:
        return my_marker

a_var = get_object_or_a_singleton_marker()

if a_var is not my_marker:
    # 此处a_var类型会被收窄为int
    reveal_type(a_var)  # 类型检查器将显示:int
else:
    # 此处a_var类型为Literal["This is very singletony, I promise!"]
    reveal_type(a_var)

二、类实例单例场景

同样用Final标记单例实例,返回类型直接声明为目标类型与单例类的联合,is判断会触发类型收窄:

from typing import Final, Union

class SingletonMarker:
    # 实现单例逻辑
    _instance = None
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

my_marker: Final[SingletonMarker] = SingletonMarker()

def get_obj_or_singleton() -> Union[int, SingletonMarker]:
    some_condition_is_met = False  # 示例条件
    if some_condition_is_met:
        return 456
    else:
        return my_marker

a_var = get_obj_or_singleton()

if a_var is not my_marker:
    # 此处a_var类型收窄为int
    reveal_type(a_var)
else:
    # 此处a_var类型为SingletonMarker(且是唯一实例)
    reveal_type(a_var)

关键说明

  • 之前的写法无效是因为:直接用my_marker作为类型表达式不符合语法;未标记Final时,Literal[my_marker]无法被识别为固定字面量;type[my_marker]返回的是实例的泛型类型(如str),而非特定实例,因此无法触发精确的类型收窄。
  • 上述方案在主流类型检查器(如mypy、pyright)中均能正常工作,无需额外辅助函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 20:08:23