获取类属性的定义顺序,摘抄至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还原过去,

 

上面代码的需求:

我们想自动记录下属性和方法在类中定义的顺序。这样就能利用这个顺序来完成各种操作(例如序列化处理、将属性映射到数据库中等)

posted @ 2020-09-25 10:53  就是想学习  阅读(248)  评论(0编辑  收藏  举报