如何在Python 2中实现带有序属性与字典接口的类?
Python 2 实现有序属性类的方案
实现思路
要满足需求,需结合元类记录类定义阶段的属性顺序,用OrderedDict维护实例新增属性的顺序,再通过特殊方法实现点访问与字典式访问的兼容,最后适配json.dumps的序列化逻辑。
完整代码实现
from collections import OrderedDict import json class OrderedAttrMeta(type): def __new__(cls, name, bases, attrs): # 收集类定义中的非方法属性,按定义顺序存储 declared_attrs = [] for attr_name, attr_value in attrs.items(): if not callable(attr_value) and not attr_name.startswith('__'): declared_attrs.append(attr_name) # 将属性顺序绑定到类上 attrs['_declared_attrs'] = declared_attrs return super(OrderedAttrMeta, cls).__new__(cls, name, bases, attrs) class MyClass(object): __metaclass__ = OrderedAttrMeta someprop = 1 otherprop = "" thirdprop = "" def __init__(self): # 用OrderedDict存储实例新增属性,保证顺序 self._instance_attrs = OrderedDict() def say_hello(self): print("hello {}".format(self.someprop)) # 支持字典式获取属性 def __getitem__(self, key): if key in self._instance_attrs: return self._instance_attrs[key] return getattr(self, key) # 支持字典式设置属性 def __setitem__(self, key, value): self._instance_attrs[key] = value # 同步设置为实例属性,支持点访问 setattr(self, key, value) def keys(self): # 合并类定义属性与实例新增属性,排除方法 result = self._declared_attrs[:] result.extend(self._instance_attrs.keys()) return result # 让json.dumps能正确遍历键 def __iter__(self): for key in self.keys(): yield key # 序列化时返回有序字典,保证输出顺序 def __getstate__(self): ordered_dict = OrderedDict() for key in self.keys(): ordered_dict[key] = getattr(self, key) return ordered_dict # 测试代码 if __name__ == "__main__": myobj = MyClass() myobj.newprop = "test" # 测试点访问与字典访问 print(myobj.newprop) # 输出: test print(myobj["newprop"]) # 输出: test # 测试keys()顺序 print(myobj.keys()) # 输出: ['someprop', 'otherprop', 'thirdprop', 'newprop'] # 测试json序列化 json_str = json.dumps(myobj) print(json_str) # 输出: {"someprop": 1, "otherprop": "", "thirdprop": "", "newprop": "test"}
关键细节说明
- 元类
OrderedAttrMeta:在类创建阶段遍历属性,筛选出非方法、非内置双下划线开头的属性,按定义顺序存入_declared_attrs,确保类属性的顺序。 - 实例属性维护:用
_instance_attrs这个OrderedDict保存实例新增属性,保证新增属性的顺序。 - 双访问兼容:通过
__getitem__和__setitem__实现字典式访问,设置属性时同步调用setattr,保证点访问可用。 - json序列化适配:实现
__iter__让json模块能遍历键,__getstate__返回有序字典,确保序列化后的json字符串顺序符合预期。
内容的提问来源于stack exchange,提问作者sdbbs
相关产品推荐
相关产品推荐

