设为首页 收藏本站
查看: 1004|回复: 0

[经验分享] metaclass in python (part 1)

[复制链接]

尚未签到

发表于 2017-4-29 07:22:06 | 显示全部楼层 |阅读模式
python 的东西虽然概念上容易理解 ,但是实际用起来却也不都是那么容易的。这个 metaclass 就是典型一例。虽然早知道了它是什么,不过要说出它具体能干点啥,一时半会还真想不起来。
先看看官方文档中的定义吧:
__metaclass__  This variable can be any callable accepting arguments for name,  bases, and dict. Upon class creation, the callable is  used instead of the built-in type(). New in version 2.2.   The appropriate metaclass is determined by the following precedence rules:  


  • If dict['__metaclass__'] exists, it is used.
  • Otherwise, if there is at least one base class, its metaclass is used (this  looks for a __class__ attribute first and if not found, uses its  type).
  • Otherwise, if a global variable named __metaclass__ exists, it is used.
  • Otherwise, the old-style, classic metaclass (types.ClassType) is used.
  The potential uses for metaclasses are boundless. Some ideas that have been  explored including logging, interface checking, automatic delegation, automatic  property creation, proxies, frameworks, and automatic resource  locking/synchronization.
  看完这个似乎又能理清了一点东西:所谓 new-style class 和 old-style class 最根本的区别其实正在于它们的 metaclass 一个是 type,一个是 types.ClassType,所以只要一个 class 继承自 object 而又没有指定自己的 __metaclass__ 的话,其 metaclass 就会自动使用基类 object 的 __metaclass__,但是 object 却没有 __metaclass__,那就使用 type(object),也就是 type 了!


然后再 google 一下(这次是要 google code 一下了),看看实际生活中的代码都用它来干了点啥。不搜不知道,这一搜还真发现不少有意思的结果:

  • 第一条[地址],是twisted里的代码
    __metaclass__ = type
    真有创意!根据上面定义中 __metaclass__ 查找顺序,在使用 old-style class 的 metaclass (也就是types.ClassType)之前会找一下全局变量 __metaclass__ ,而上面代码中通过定义模块全局变量 __metaclass__ ,使得模块中原来的 old-style class 立刻变成了 new-style class。使用这种方法来将 old-style class 升级为 new-style class,确实省了不少代码,毕竟将来的 python 中将会只存在 new-style class ,那时候便可放心地将这一句去掉了。聪明!(不过这样会导致查找 metaclass 的过程要多了几个步骤,效率上可能就 ... )
  • 第二条[地址],从这个例子的路径看它是在 python25/tools/ 下面,不过翻了一下自己python25 安装目录下却没有发现这些代码,郁闷!
    在这个例子中,__metaclass__ 被当成了一种快捷定义 class 方法的方式了。
    我们知道在 class 中定义的方法其实默认都是 instance 方法,要使它们成为 class 方法需要使用 classmethod 进行装饰,对于有大量 class 方法的类来说,这的确是有点小麻烦。
    既然 class 中定义的方法是 class 的 instance 方法,那么在 type 中定义的方法岂不就是 type 的 instance 方法,也就正好是 class 方法了?
    这个例子便是利用这一点,通过继承 type,添加 type 的 instance 方法,也就是添加了 class 方法了。好聪明啊,呵呵 ;-)
  • 第三条的用法与第一条类似,第四条[地址]来自传说中的 psyco !一看到这个名字差点没有勇气继续看下去了,不过还好,这个 metaclass 其实并不复杂,它的作用就是在 class 创建之后自动将它或 __psyco_bind__ 中指定的属性 bind 到 psyco,具体 bind 干了什么事情就只有对 psyco 有研究的兄弟来解答了,不过估计这样就可以进行某种特别的优化了。也许你要说了:这个工作也可以在 class 的 __init__ 或是 __new__ 方法里做啊。但是放在 __init__ 里面做的话你就需要其他的 class 都来继承你这个基类了,而使用 __new__ 的问题是它可以被子类 override 掉。
    使用 metaclass 的另一个好处是,你可以神不知鬼不觉地修改 class 的创建过程,比如
    这个例子里面,在模块中定义好 __metaclass__ 全局变量,那当其他的代码 from module import * 的时候,该 __metaclass__ 的定义就会自动作用于其后所定义的所有 class 了。
  • 第五条和第八条的用法也和第一条类似,第六条貌似只是在使用 __metaclass__ 的情况下对 pickle  进行测试,没有什么特别的。至于第七条。。。。

而至于第七(来自zope)和第九(来自sqlobject)两条,还是听下回分解吧。
不好意思,真的不是我卖关子,实在是被第七条整晕了 = =",真不知道写这些代码的人是怎么想的,呵呵。
希望大家能从这些代码中看到 metaclass 的强大,动态语言的灵活。什么?还没看到?去看看这个去!

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-370556-1-1.html 上篇帖子: Snow Leopard 安装 Python MySQLdb 记录 下篇帖子: Python的网络编程(一)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表