• python自定义元类metaclass,约束子类


    python自定义元类,约束子类

    """
    对象的类型称为类,类的类就称为元类。Python 中对元类实例化的结果就是“普通类”,这个过程是动态的。
    在定义类时可以指定元类来改变类的创建过程。

    你想创建某一批类全部必须实现某种方法属性,则可通过 metaclass = ModelBase 来实现。
    若在继承了type的类如:ModelBase(type),并重写 new() 方法,使用 metaclass 可以在创建类时动态修改类定义。

    new(cls,) 用来创建一个(未初始化)实例;init(self,) 则是用来初始化一个实例。
    在定义metaclass = ModelBase元类的 new 方法中,因为类实例还没有创建,所以可以更改最后生成类的各项属性:诸如名称,基类或属性,方法等。
    而在 init 中由于类已经创建完成,所以无法改变。
    """

    class ModelBase(type):
        """
        cls   代表动态修改的类
        name  字符串类型,存放新类的名字
        bases 元组(tuple)类型,指定类的基类/父类
        attrs  字典类型,存放该类的所有属性(attributes)和方法(method)
        """
    
    
        def __new__(cls, name, bases, attrs, ):
            super_new = super().__new__
            # 还确保初始化只对模型子类执行(不包括模型类本身)
            parents = [b for b in bases if isinstance(b, ModelBase)]
            if not parents:
                # 创建子类,动态添加方法
                attrs['totalpay'] = lambda self: self.price * self._discount if self.price and self._discount else None
                return super_new(cls, name, bases, attrs)
    
    
    class storeModel(metaclass=ModelBase):
        __slots__ = ('name', 'price', '_discount')
    
        def __init__(self, name, price):
            self.name = name
            self.price = price
    
        @property
        def discount(self):
            return self._discount
    
        @discount.setter
        def discount(self, discount):
            self._discount = discount
    
        @property
        def run(self):
            print("七夕节给女朋友买{}一共花费{}···".format(self.name, self.totalpay()))
    
    
    # 实例化
    obj = storeModel('苹果', 1000)
    obj.discount = 0.1
    obj.run
    
    obj = storeModel('香蕉', 100000)
    obj.discount = 0.1
    obj.run
    
    # 内置函数反射方法,直接修改
    setattr(storeModel, 'price', 2000)
    obj.run
  • 相关阅读:
    python2.7升python3.2
    SQL-基础学习使用的数据库资料
    SQL-基础学习2--ORDER BY ,DESC,WHERE, BETWEEN,AND ,OR ,IN ,NOT
    SQL-基础学习1--SELECT,LIMIT,DISTINCT,注释
    Python之Django-part 1
    python--文本处理1
    EXTJS4.2——8.Form+gride+linq进行前后端传输
    LINQ的实例
    高级委托使用
    C# 委托
  • 原文地址:https://www.cnblogs.com/justblue/p/13562119.html
Copyright © 2020-2023  润新知