为何Slots无法与Dataclass的Final属性配合使用?
问题原因
当你在使用slots=True的数据类中定义VERSION: Final[str] = '1.0.0'时:
- 由于未标记为
ClassVar,数据类会将VERSION视为实例字段而非类变量。 - 启用
slots=True后,该字段会被定义为实例的槽位,此时类本身的VERSION属性指向的是数据类的字段元数据(Field对象),而非你设置的默认字符串值'1.0.0'。 - 在类方法中访问
cls.VERSION时,你拿到的是这个Field对象,将其与字符串'1.0.0'比较自然会返回False。
移除slots=True时,数据类会将类属性VERSION设置为默认值'1.0.0',所以比较会生效,但这并非正确做法——因为VERSION本应是类级别的常量。
正确修复方案
需要同时使用ClassVar和Final来标记VERSION:
ClassVar告诉数据类这是一个类变量,不会将其作为实例字段处理(也就不会生成对应的槽位)。Final标记该变量为不可修改的常量(类型检查器会强制执行,Python运行时虽不严格限制,但能明确表达意图)。
修复后的代码如下:
#!/usr/bin/env python3 from __future__ import annotations from dataclasses import dataclass from typing import Final, ClassVar @dataclass(slots=True) class Child(): VERSION: ClassVar[Final[str]] = '1.0.0' @classmethod def check_version(cls, version: str) -> bool: return version == cls.VERSION print(Child.check_version('1.0.0')) # Returns True
这样修改后,Child.VERSION会正确指向字符串'1.0.0',类方法的比较结果也会符合预期。
内容的提问来源于stack exchange,提问作者NicoHood
相关产品推荐
相关产品推荐

