python类创建过程

来源:互联网 发布:苹果mac系统更新不了 编辑:程序博客网 时间:2024/06/18 08:13
类创建过程
#coding=utf8import abcimport collectionsclass AutoStorage:    """描述符"""    __counter = 0    def __init__(self):        cls = self.__class__        prefix = cls.__name__        index = cls.__counter        self.storage_name = '_{}#{}'.format(prefix, index)        cls.__counter += 1    def __get__(self, instance, owner):        if instance is None:            return self        else:            return getattr(instance, self.storage_name)    def __set__(self, instance, value):        setattr(instance, self.storage_name, value)class Validated(abc.ABC, AutoStorage):    """描述符子类,增加抽象方法validate用于验证数据有效性"""    def __set__(self, instance, value):        value = self.validate(instance, value)        super().__set__(instance, value)    @abc.abstractmethod    def validate(self, instance, value):        """return validated value or raise ValueError"""class Quantity(Validated):    """用于验证的实现类       a number greater than zero"""    def validate(self, instance, value):        if value <= 0:            raise ValueError('value must be > 0')        return valueclass NonBlank(Validated):    """用于验证的实现类       a string with at least one non-space character"""    def validate(self, instance, value):        value = value.strip()        if len(value) == 0:            raise ValueError('value cannot be empty or blank')        return valueclass EntityMeta(type):    """元类,用于创建类       Metaclass for business entities with validated fields"""    @classmethod    def __prepare__(cls, name, bases):        """<1>python3.4新增方法,在所有类定义开始执行前首先被调用,用来创建类命名空间。              这里通过返回了一个OrderedDict而不是一个普通的字典,可以很容易的捕获定义的顺序。"""        return collections.OrderedDict()    def __new__(cls, name, bases, attr_dict):        """<2>用来实例化最终的类对象。              cls为EntityMeta,name为LineItem,此方法创建LineItem类对象并传递给__init__方法初始化"""        d = dict(attr_dict)        order = []        for name, value in attr_dict.items():            order.append(name)        d['_order'] = order        return type.__new__(cls, name, bases, d)    def __init__(cls, name, bases, attr_dict):        """<3>最后被调用,用来执行其他的一些初始化工作。              cls为类对象LineItem,此处应该为self,用cls是为了表示要构建的实例是类,              name为LineItem,接收__new__方法创建的类对象,初始化类属性"""        super().__init__(name, bases, attr_dict)        cls._field_names = []  # <2>        for key, attr in attr_dict.items():            if isinstance(attr, Validated):                type_name = type(attr).__name__                attr.storage_name = '_{}#{}'.format(type_name, key)  # 设置描述符实例对象属性名称                cls._field_names.append(key)    def __call__(self, *args, **kwargs):        """<4>创建子类实例时调用,会调用子类__init__方法初始化对像"""        super().__call__(*args, **kwargs)class Entity(metaclass=EntityMeta):    """Business entity with validated fields"""    @classmethod    def field_names(cls):        for name in cls._field_names:            yield nameclass LineItem(model.Entity):    description = model.NonBlank() # 描述符对象,检查值不能为空    weight = model.Quantity()      # 描述符对象,检查值不能小于等于0    price = model.Quantity()       # 描述符对象,检查值不能小于等于0    def __init__(self, description, weight, price):        """<5>类为可调用对象,由元类的__call__调用"""        self.description = description   # 调用描述符对象的__set__方法        self.weight = weight             # 调用描述符对象的__set__方法        self.price = price               # 调用描述符对象的__set__方法    def subtotal(self):        return self.weight * self.priceif __name__ == '__main__'    raisins = LineItem('Golden raisins', 10, 6.95)    print(raisins.weight, raisins.description, raisins.price)  # 调用描述述对象的__get__方法
原创粉丝点击