获取类属性的定义顺序,摘抄至PythonCookBook
# 描述符 + 元类 爽爆天 from collections import OrderedDict # 描述符的基类,通过类属性来指定参数 class Typed: # 赋值类型给子类继承用 _expected_type = type(None) def __init__(self, name=None): self._name = name def __set__(self, instance, value): if not isinstance(value, self._expected_type): raise TypeError('Expected' + str(self._expected_type)) instance.__dict__[self._name] = value class Integer(Typed): _expected_type = int class Float(Typed): _expected_type = float class String(Typed): _expected_type = str # 前面的都还算常规操作,懂描述符的肯定要想,取值的时候,如何取值 class OrderedMeta(type): def __new__(cls, clsname, bases, clsdict): # 这里又到时候返回给__init__的时候一个普通字典 d = dict(clsdict) order = [] # Orderdict就是用来给这里赋值描述符实例的_name用的 # 为了后续的方法as_csv输出不要出现顺序问题 # 所以for循环的时候,用了clsdict这个有序字典,返回的时候又给了普通字典 # 因为默认的就是普通的字典,你用有序字典也没问题,但还是返回一个普通的不会出现兼容问题 for name, value in clsdict.items(): if isinstance(value, Typed): # 这个就更加厉害了,通过描述符的赋值操作,修改描述符实例的属性名,后面直接可以通过属性名取值 value._name = name order.append(name) # 这个列表就是到时候用来去描述符属性用的,也就是给as_csv用的 d['_order'] = order return super(OrderedMeta, cls).__new__(cls, clsname, bases, d) @classmethod def __perpare__(cls, clsname, bases): return OrderedDict() class Structure(metaclass=OrderedMeta): def as_csv(self): return ','.join(str(getattr(self,name)) for name in self._order) class Stock(Structure): name = String() shares = Integer() price = Float() def __init__(self, name, shares, price): self.name = name self.shares = shares self.price = price s = Stock('GOOD', 100, 490.1) print(s.name) print(s.as_csv())
上面是完整的代码摘抄,确实写的很棒,那是相当的厉害。啥时候等我这么厉害就爽大了。
OrderedDict的使用,让我也能更加清晰的认识到,为什么要用,需要的时候才用到。
但类的属性,本来用的是普通的dict,所以书中后面又用dict还原过去,
上面代码的需求:
我们想自动记录下属性和方法在类中定义的顺序。这样就能利用这个顺序来完成各种操作(例如序列化处理、将属性映射到数据库中等)