如何通过编程方式获取Python dataclass的属性名称?
如何通过编程方式获取Python dataclass的属性名称?
我懂你的痛点!直接用TestDataclass.property1.__name__确实行不通,因为dataclass定义的属性是属于实例层面的,类本身并没有挂载这个属性对象,所以才会抛出AttributeError。不过不用担心,有几种简单靠谱的方法能帮你实现「不用硬编码属性名」的需求,完美适配你的依赖注入场景:
方法1:用dataclasses内置的fields()函数(最推荐)
dataclasses模块专门提供了fields()函数,可以直接获取到dataclass所有字段的元信息,其中就包含字段名称。这是最准确、最贴合dataclass场景的方式:
from dataclasses import dataclass, fields @dataclass(init=True) class TestDataclass: property1: str # 获取单个字段的名称 # 只在这一处硬编码,比在DI容器里写字符串更易维护 target_field = next(field for field in fields(TestDataclass) if field.name == "property1") print(target_field.name) # 输出: property1 # 存入依赖注入容器 di[target_field.name] = "这样就算以后改了属性名,只需要修改这里的硬编码,DI逻辑不用动" # 如果要批量处理所有字段,可以遍历fields结果 for field in fields(TestDataclass): di[field.name] = f"对应{field.name}的注入值"
方法2:直接访问类的__annotations__属性
Python的类会把所有类型注解存在__annotations__字典里,dataclass也不例外,字典的键就是属性名称:
# 获取所有属性名 print(TestDataclass.__annotations__.keys()) # 输出: dict_keys(['property1']) # 单个获取 property1_name = list(TestDataclass.__annotations__.keys())[0] di[property1_name] = "简单直接,适合字段少的场景"
不过要注意:__annotations__会包含类中所有的类型注解,如果你后来给类加了其他非dataclass字段的注解,这个方法会拿到多余的内容,所以用fields()会更精准。
方法3:完全避免硬编码的进阶技巧(适合属性易变的场景)
如果想彻底告别硬编码,哪怕是一处都不想写,可以结合枚举来维护字段名,这样属性名修改时只需要同步枚举和dataclass定义:
from dataclasses import dataclass, field from enum import Enum # 枚举维护字段名 class TestDataclassFields(Enum): PROPERTY1 = "property1" @dataclass(init=True) class TestDataclass: # 用metadata绑定枚举值,或者也可以直接使用枚举 property1: str = field(metadata={"field_key": TestDataclassFields.PROPERTY1}) # 存入DI容器时直接用枚举值 di[TestDataclassFields.PROPERTY1.value] = "以后改属性名,只需要修改枚举和dataclass的属性定义,DI代码完全不用动"
最后再解释下你原来的写法为什么失败:dataclass在定义时,并没有把property1作为类属性创建出来,只有当你实例化TestDataclass后,实例对象才会有property1这个属性,所以直接访问TestDataclass.property1自然会找不到属性啦。
备注:内容来源于stack exchange,提问作者Dzeri96
相关产品推荐
相关产品推荐

