Python 3.14+ 中,类型边界/约束能否存储在全局变量中并用于泛型函数定义?

“我希望公开回答这些问题,因为所使用的片段可能会非常误导。”

来源 – https://stackoverflow.com/q/79917832

发布者:罗德里戈·托雷斯

检索于2026年3月31日,许可证 – CC BY-SA 4.0

# 在 types.py 中
type Scalar = bool | int | str |float
SCALAR_TYPES = (bool, int, str, float)

进入全屏模式
退出全屏模式

是的,它可以工作,但你所做的只有一部分实际上是“真实”的输入,这一点很重要。

以下是你代码片段的清晰分解

真正可靠和正确的部分

这是完全有效的,并且符合现代输入风格(PEP 695 风格):

type Scalar = bool | int | str | float`


def extract_scalar[T: Scalar](data: dict, key: str, expected: type[T]) -> T: ...
进入全屏模式
退出全屏模式

请注意,Scalar 是一个正确的类型别名,而 T: Scalar 是一个约束

这是我推荐的方法

让我们看看什么是有效的,但有点误导

SCALAR_TYPES = (bool, int, str, float)

def extract_scalar[T: SCALAR_TYPES](...) -> T: ...
进入全屏模式
退出全屏模式

是的,这段代码可以运行。是的,类型检查器可能会接受它。

但这里有个问题:

SCALAR_TYPES 只是一个运行时元组

它不是一个类型级别的构造

PEP 695 期望约束是字面元组,而不是变量

所以即使 Python 3.14(结合 PEP 649 的延迟注解)在语法上允许这样做,你仍然依赖于以下行为:

不被类型规范保证

在工具之间可能不一致

在未来的更新中容易被破坏

所以,简单来说:你是在将运行时值与类型系统意图混合

实用建议(你应该实际采取的行动)

你的思路是正确的——重用和集中化是好的。只需清晰地划分责任:

# types.py
type Scalar = bool | int | str | float
SCALAR_TYPES = (bool, int, str, float)

进入全屏模式
退出全屏模式

然后:

# 类型检查部分
def extract_scalar[T: Scalar](...) -> T: ...

# 运行时验证部分
if not isinstance(value, SCALAR_TYPES):
    ...
进入全屏模式
退出全屏模式

请使用:类型别名进行类型检查,使用元组进行运行时检查

不要试图让一个同时完成这两项工作。

更多