如何将Python对象的指定属性导出为字典?
实现带标记@property属性导出为字典的其他方法
以下是几种替代你当前实现的方案,各有适用场景:
1. 元类预收集导出属性
通过元类在类定义阶段就把标记了@export_to_dict的属性名记录下来,避免每次调用to_dict时遍历所有属性,提升调用效率。
def export_to_dict(func): func._export_to_dict = True return func class ExportMeta(type): def __new__(cls, name, bases, attrs): export_attrs = [] for attr_name, attr_value in attrs.items(): # 识别@property装饰的属性,检查其fget方法的标记 if isinstance(attr_value, property) and hasattr(attr_value.fget, '_export_to_dict'): export_attrs.append(attr_name) attrs['_export_attrs'] = export_attrs return super().__new__(cls, name, bases, attrs) class Foo(metaclass=ExportMeta): @export_to_dict @property def bar1(self): return 1 @property def bar2(self): return {"smth": 2} @export_to_dict @property def bar3(self): return "a" @property def bar4(self): return [2, 3, 4] def to_dict(self): return {attr: getattr(self, attr) for attr in self._export_attrs}
2. 自定义Property子类
创建继承自property的专属子类,直接用它标记需要导出的属性,to_dict时通过类型筛选即可。
class ExportProperty(property): pass class Foo: @ExportProperty # 用自定义子类替代原生@property def bar1(self): return 1 @property def bar2(self): return {"smth": 2} @ExportProperty def bar3(self): return "a" @property def bar4(self): return [2, 3, 4] def to_dict(self): result = {} # 遍历类属性,筛选ExportProperty类型 for attr_name, attr_value in self.__class__.__dict__.items(): if isinstance(attr_value, ExportProperty): result[attr_name] = getattr(self, attr_name) return result
3. 利用函数注解实现标记
不需要额外装饰器,直接给@property的方法添加自定义注解,to_dict时读取注解判断是否导出。
class Foo: @property def bar1(self): return 1 # 给属性的fget方法添加导出标记 bar1.fget.__annotations__['export'] = True @property def bar2(self): return {"smth": 2} @property def bar3(self): return "a" bar3.fget.__annotations__['export'] = True @property def bar4(self): return [2, 3, 4] def to_dict(self): result = {} for attr_name, attr_value in self.__class__.__dict__.items(): if isinstance(attr_value, property): # 检查注解中的导出标记 if attr_value.fget.__annotations__.get('export', False): result[attr_name] = getattr(self, attr_name) return result
4. 类装饰器收集导出属性
和元类思路类似,但用类装饰器实现,无需修改元类,更轻量化。
def export_to_dict(func): func._export_to_dict = True return func def collect_export_attrs(cls): export_attrs = [] for attr_name, attr_value in cls.__dict__.items(): if isinstance(attr_value, property) and hasattr(attr_value.fget, '_export_to_dict'): export_attrs.append(attr_name) cls._export_attrs = export_attrs return cls @collect_export_attrs class Foo: @export_to_dict @property def bar1(self): return 1 @property def bar2(self): return {"smth": 2} @export_to_dict @property def bar3(self): return "a" @property def bar4(self): return [2, 3, 4] def to_dict(self): return {attr: getattr(self, attr) for attr in self._export_attrs}
各方案特点
- 元类/类装饰器:适合多类复用导出逻辑的场景,提前收集属性,
to_dict调用更高效 - 自定义Property子类:语法简洁直观,可读性强
- 函数注解:无需额外装饰器,利用Python原生特性,但标记方式稍显繁琐
内容的提问来源于stack exchange,提问作者StuffHappens
相关产品推荐
相关产品推荐

