打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
十九、Python MetaClass元类详解
type() 函数更适合于动态地创建相对简单的类,如果要创建更复杂的类,则需要通过 MetaClass(元类)的方式。

MetaClass(元类),简单的理解,就是创建类的类,即创建类之后,再由类来创建实例进行应用。使用元类可以在创建类时动态修改类定义。为了使用元类动态修改类定义,程序需要先定义元类。

定义元类时,需令其继承与 type 类,且默认的命名习惯是,让类名以 MetaClass 结尾。不仅如此,元类中需要定义并实现 __new__() 方法(一定要有返回值)。因为元类在创建类时,该 __new__() 方法将会被调用,用来生成新建的类。

之所有要求元类继承 type 并实现 __new__() 方法,是因为在创建类时,内部调用了 type 的 __new__() 方法为这个类分配内存空间,当内存分配完成后,便会调用 type 的 _init__ 方法初始化。


下面程序定义了一个元类类:
  1. # 定义Item元类,继承type

  2. class ItemMetaClass(type):

  3. # cls代表动态修改的类

  4. # name代表动态修改的类名

  5. # bases代表被动态修改的类的所有父类

  6. # attr代表被动态修改的类的所有属性、方法组成的字典

  7. def __new__(cls, name, bases, attrs):

  8. # 动态为该类添加一个cal_price方法

  9. attrs['cal_price'] = lambda self: self.price * self.discount

  10. return type.__new__(cls, name, bases, attrs)

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

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

例如,如下程序使用元类定义了两个类:
  1. # 定义Book类

  2. class Book(metaclass=ItemMetaClass):

  3.     __slots__ = ('name', 'price', '_discount')

  4.     def __init__(self, name, price):

  5.         self.name = name

  6.         self.price = price

  7.     @property

  8.     def discount(self):

  9.         return self._discount

  10.     @discount.setter

  11.     def discount(self, discount):

  12.         self._discount = discount

  13. # 定义cellPhone类

  14. class CellPhone(metaclass=ItemMetaClass):

  15.     __slots__ = ('price', '_discount' )

  16.     def __init__(self, price):

  17.         self.price = price

  18.     @property

  19.     def discount(self):

  20.         return self._discount

  21.     @discount.setter

  22.     def discount(self, discount):

  23.         self._discount = discount

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

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

  2. b.discount = 0.76

  3. # 创建Book对象的cal_price()方法

  4. print(b.cal_price())

  5. cp = CellPhone(2399)

  6. cp.discount = 0.85

  7. # 创建CellPhone对象的cal_price()方法

  8. print(cp.cal_price())

运行上面程序,可以看到如下运行结果:

67.64
2039.1499999999999

从上面的运行结果来看,通过使用元类可以动态修改程序中的一批类,对它们集中进行某种修改。这个功能在开发一些基础性框架时非常有用,程序可以通过使用元类为某一批需要具有通用功能的类添加方法。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
Python面向对象特征总结
Python中用MetaClass实现委托、不可变集合
python学习笔记之七:魔法方法,属性
《源码探秘 CPython》72. 自定义类对象的底层实现与 metaclass(上)
[精]两句话掌握 Python 最难知识点:元类
进阶 | Python 面向切面编程与元类
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服