Python中类内部变量的不同声明方式及最优方案选择
Python类静态常量三种实现的差异与选型
功能差异
三种实现的核心区别可以从所属作用域、访问逻辑、可修改性三个维度区分:
- 第一种(类属性):属性属于类本身,所有实例共享,类和实例均可直接访问,默认允许修改
- 第二种(普通property):属性属于实例级别的动态计算属性,每次访问都会重新执行返回逻辑,仅实例可访问,默认只读无法修改
- 第三种(cached_property):属性属于实例级别的缓存属性,仅第一次访问时执行返回逻辑,结果会存入实例属性缓存,后续访问直接取缓存值,仅实例可访问,缓存生成后允许修改
各自优缺点
1. 类属性实现
class ApplePie: type = "apple" def __init__(self): print(f"I'm an {ApplePie.type} pie!")
- 优点:实现最简单,内存占用最低,类和实例都可直接访问,修改类属性即可全局生效,不需要额外导入依赖
- 缺点:没有只读保护,容易被意外修改(无论是类层面修改
ApplePie.type还是实例层面赋值self.type都会覆盖原有值),不支持动态计算返回值
2. 普通property实现
class ApplePie: @property def type(self) -> str: return "apple" def __init__(self): print(f"I'm an {self.type} pie!")
- 优点:天然只读,不会被意外修改,支持在返回逻辑里加动态计算规则,适合需要实时生成返回值的场景
- 缺点:每次访问都会执行一次方法,有微小的性能开销(逻辑复杂时开销会放大),仅支持实例访问,类无法直接调用该属性
3. cached_property实现
from functools import cached_property class ApplePie: @cached_property def type(self) -> str: return "apple" def __init__(self): print(f"I'm an {self.type} pie!")
- 优点:仅第一次访问时执行返回逻辑,后续访问直接取缓存,性能优于普通property,也支持首次生成时加复杂计算逻辑
- 缺点:需要额外导入依赖,缓存生成后可以被实例修改,也不支持类直接访问,若返回值需要动态更新则不适用
其他可选的更优实现
根据场景还有三种更常用的实现方案:
- 带Final标注的类属性
from typing import Final class ApplePie: type: Final[str] = "apple" def __init__(self): print(f"I'm an {ApplePie.type} pie!")
在原有类属性的基础上加Final类型标注,静态检查阶段就会禁止修改该属性,既能保留类属性的所有优点,又能避免被意外修改,适合纯常量场景。
2. 枚举类实现
from enum import Enum class PieType(Enum): APPLE = "apple" class ApplePie: def __init__(self): print(f"I'm an {PieType.APPLE.value} pie!")
如果存在多个固定的类型常量,用枚举类实现规范性更强,完全避免硬编码,也天然不允许修改,适合多常量枚举的场景。
3. 类级别property(Python 3.9+支持)
class ApplePie: @classmethod @property def type(cls) -> str: return "apple" def __init__(self): print(f"I'm an {cls.type} pie!")
实现类级别的只读属性,类和实例都可以访问,同时保留只读特性,适合需要类层面访问动态属性的场景。
日常开发选型逻辑
我会根据场景灵活选择:
- 纯固定常量场景:优先选带
Final标注的类属性,实现最简单、性能最高,还有静态检查防修改的能力,90%的常规场景都适用 - 需要动态计算、且值每次访问都要更新的场景:选普通
@property - 需要动态计算、且值生成后不会变化的场景:选
cached_property降低性能开销 - 多固定常量的场景:选枚举类,避免硬编码错误
内容的提问来源于stack exchange,提问作者Tim Estes
相关产品推荐
相关产品推荐

