获取类属性的定义顺序,摘抄至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还原过去,
上面代码的需求:
我们想自动记录下属性和方法在类中定义的顺序。这样就能利用这个顺序来完成各种操作(例如序列化处理、将属性映射到数据库中等)
浙公网安备 33010602011771号