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

Python中如何创建真正不可变常量?Final为何未生效?

问题解答

为什么Final标注后仍能修改对象?

typing.Final仅作用于静态类型检查层面,用来约束变量不能被重新赋值,而非在运行时强制限制对象本身的可变性:

  • 你的代码中,y: Final[Sequence[str]]只是告诉类型检查器(如mypy、pyright):y这个变量不能被重新指向其他对象,但它指向的列表本身是可变的。
  • Python解释器在运行时完全忽略Final标注,所以y.append('x')能正常执行——你修改的是列表对象的内容,而非重新给y赋值。
  • 文档里的"Error"是类型检查器给出的静态提示,不是Python运行时的报错。只有用类型检查工具扫描代码才会看到该错误,直接运行脚本不会触发。

2024年Python创建不可变常量的最佳方案

根据需求场景选择对应方案:

1. 基础不可变类型(数值、字符串、元组)

直接用大写命名规范+Final标注即可,这类类型本身不可变,Final用来防止变量被重新赋值:

from typing import Final

MAX_RETRIES: Final[int] = 3
DEFAULT_NAME: Final[str] = "admin"
ALLOWED_EXTENSIONS: Final[tuple[str, ...]] = ("jpg", "png")

2. 不可变容器

  • 不可变字典:用types.MappingProxyType包装普通字典,运行时无法修改:
    from types import MappingProxyType
    
    immutable_dict = MappingProxyType({"key1": "value1", "key2": "value2"})
    immutable_dict["key3"] = "value3"  # 运行时报错: TypeError
    
  • 不可变序列:优先使用元组(本身不可变),但注意元组内的元素如果是可变对象(如列表),元素内部仍可修改。

3. 自定义不可变对象

  • @dataclass(frozen=True):你当前使用的方案是最直接的官方原生方案,适合复杂数据结构,无需额外依赖:
    from dataclasses import dataclass
    
    @dataclass(frozen=True)
    class Config:
        host: str
        port: int
        timeout: int
    
    cfg = Config("localhost", 8080, 30)
    cfg.port = 8000  # 运行时报错: FrozenInstanceError
    
  • 第三方库attrs:如果需要更灵活的配置(如字段验证、类型转换),可以用attrs的@frozen装饰器,功能比原生dataclass更丰富:
    import attrs
    
    @attrs.frozen
    class User:
        id: int
        name: str
        email: str
    
  • 手动实现不可变性:重写__setattr__和__delattr__方法,但代码繁琐,仅适合特殊场景:
    class ImmutableObject:
        def __init__(self, value):
            self._value = value
    
        @property
        def value(self):
            return self._value
    
        def __setattr__(self, name, value):
            if name != "_value" or hasattr(self, "_value"):
                raise TypeError("Cannot modify immutable object")
            super().__setattr__(name, value)
    
        def __delattr__(self, name):
            raise TypeError("Cannot delete attributes from immutable object")
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 17:40:24