如何在Python中创建不可变的列表(或其他值):真正的常量?

-1 投票
1 回答
116 浏览
提问于 2025-04-14 18:12

在一个旧讨论中,我发现提到了输入Final的内容。我试了试文档中的例子

y: Final[Sequence[str]] = ['a', 'b']
y.append('x')  # Error: "Sequence[str]" has no attribute "append"
z: Final = ('a', 'b')  # Also works

但是和文档说的不一样的是,它把y改成了['a','b','x'],没有报错。我现在用的是Python 3.11。这是怎么回事?而且,2024年在Python中创建不可变常量的最新方法是什么呢?

目前我使用@dataclass(frozen=True)来实现不可变性,但可能还有更简单的方法。

旧讨论对Python 3.10+的现代特性没有帮助。

1 个回答

3

类型检查器只能在代码运行前给你一些提示,告诉你这里可能有问题。在代码运行时,Python解释器并不在乎类型提示说了什么。(当然,如果你使用像Pydantic这样的库,它会强制执行这些规则,但这不是我们要讨论的内容)

接下来我们聊聊 Final。根据文档的解释:

typing.Final 是一个类型标记,用来表示一个变量或属性不应该被重新赋值重新定义覆盖

这里说的是给标签 y 赋值的问题!而不是改变 y 指向的对象。使用 .append() 方法是对对象的“修改”。你仍然让 y 指向同一个列表,所以这并不会阻止你。因此你不会看到任何相关的错误。这个错误来自于 Sequence。如果你想修改一个序列,你应该使用 MutableSequence

你可以用 tuple 来代替可变列表(虽然它们还有其他不同之处),或者自己创建一个类似列表的类:https://stackoverflow.com/a/22340603/13944524

撰写回答