python3 之metaclass

如果希望创建某一批类全部具有某种特征,则可通过 metaclass 来实现。使用 metaclass 可以在创建类时动态修改类定义。

为了使用 metaclass 动态修改类定义,程序需要先定义 metaclass, metaclass 应该继承 type 类,并重写 __new__() 方法。

下面程序定义了一个 metaclass 类:

#定义ItemMetaClass,继承type
class ItemMetaClass(type):
    # cls 代表动态修改的类
    # name 代表动态修改的类名
    # bases 代表被动态修改的类的所有父类
    # attrs 代表被动态修改的类的所有属性、方法组成的字典

    def __new__(cls, name, bases, attrs):
        #动态为该类添加一个cal_price方法
        attrs['cal_price'] = lambda self:self.price * self._discount
        return type.__new__(cls, name, bases, attrs)

上面程序定义了一个 ItemMetaClass 类,该类继承了 type 类,并重写了 __new__ 方法,在重写该方法时为目标类动态添加了一个 cal_price 方法。

metaclass 类的 __new__ 方法的作用是:当程序使用 class 定义新类时,如果指定了 metaclass,那么 metaclass 的 __new__ 方法就会被自动执行。

例如,如下程序使用 metaclass 定义了两个类:

#定义book类
class Book(metaclass=ItemMetaClass):
    __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


#定义cellPhone类
class CellPhone(metaclass=ItemMetaClass):
    __slots__ = ('price', '_discount')
    def __init__(self, price):
        self.price = price

    @property
    def discount(self):
        return self._discount

    @discount.setter
    def discount(self, discount):
        self._discount = discount

  

上面程序定义了 Book 和 CellPhone 两个类,在定义这两个类时都指定了 metaclass 信息,因此当 Python 解释器在创建这两个类时,ItemMetaClass 的 __new__ 方法就会被调用,用于修改这两个类。

ItemMetaClass 类的 __new__ 方法会为目标类动态添加 cal_price 方法,因此,虽然在定义 Book、CellPhone 类时没有定义 cal_price() 方法,但这两个类依然有 cal_price() 方法。如下程序测试了 Book、CellPhone 两个类的 cal_price() 方法: 

#Book类实例化
b = Book('Python基础教程', 89)
b.discount = 0.8
#Book类的cal_price()方法
print(b.cal_price())

#CellPhone类实例化
cp = CellPhone(2300)
cp.discount = 0.85
#CellPhone类的cel_price方法
print(cp.cal_price())

  

输出结果如下:

71.2
1955.0

  

  

原文地址:https://www.cnblogs.com/yjt1993/p/11103368.html