加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 教程 > 正文

畅聊 Python 的 metaclass

发布时间:2021-11-25 18:59:07 所属栏目:教程 来源:互联网
导读:注: 这是目前为止我看见的介绍 Python 的 metaclass 最为详细的文章,看完之后就可以即学即用!好东西不独享,特转载! 分享下自己对python的metaclass的知识。 一 你可以从这里获取什么? 1. 也许你在阅读别人的代码的时候碰到过metaclass,那你可以参考这

注: 这是目前为止我看见的介绍 Python 的 metaclass 最为详细的文章,看完之后就可以即学即用!好东西不独享,特转载!
 
分享下自己对python的metaclass的知识。
 
一 你可以从这里获取什么?
 
1. 也许你在阅读别人的代码的时候碰到过metaclass,那你可以参考这里的介绍。
 
2. 或许你需要设计一些底层的库,也许metaclass能帮你简化你的设计(也有可能复杂化:)
 
3. 也许你在了解metaclass的相关知识之后,你对python的类的一些机制会更了解。
 
4. more......
 
二 metaclass的作用是什么?(感性认识)
 
metaclass能有什么用处,先来个感性的认识:
 
1. 你可以自由的、动态的修改/增加/删除 类的或者实例中的方法或者属性
 
2. 批量的对某些方法使用decorator,而不需要每次都在方法的上面加入@decorator_func
 
3. 当引入第三方库的时候,如果该库某些类需要patch的时候可以用metaclass
 
4. 可以用于序列化(参见yaml这个库的实现,我没怎么仔细看)
 
5. 提供接口注册,接口格式检查等
 
6. 自动委托(auto delegate)
 
7. more...
 
三 metaclass的相关知识
 
1. what is metaclass?
 
1.1 在wiki上面,metaclass是这样定义的:In object-oriented programming,
 
a metaclass is a class whose instances are classes.
 
Just as an ordinary class defines the behavior of certain objects,
 
a metaclass defines the behavior of certain classes and their instances.
 
也就是说metaclass的实例化结果是类,而class实例化的结果是instance。我是这么理解的:
 
metaclass是类似创建类的模板,所有的类都是通过他来create的(调用__new__),这使得你可以自由的控制
 
创建类的那个过程,实现你所需要的功能。
 
1.2 metaclass基础
 
* 一般情况下, 如果你要用类来实现metaclass的话,该类需要继承于type,而且通常会重写type的__new__方法来控制创建过程。
 
当然你也可以用函数的方式(下文会讲)
 
* 在metaclass里面定义的方法会成为类的方法,可以直接通过类名来调用
 
2. 如何使用metaclass
 
2.1 用类的形式
 
2.1.1 类继承于type, 例如: class Meta(type):pass
 
2.1.2 将需要使用metaclass来构建class的类的__metaclass__属性(不需要显示声明,直接有的了)赋值为Meta(继承于type的类)
 
2.2 用函数的形式
 
2.2.1 构建一个函数,例如叫metaclass_new, 需要3个参数:name, bases, attrs,
 
name: 类的名字
 
bases: 基类,通常是tuple类型
 
attrs: dict类型,就是类的属性或者函数
 
2.2.2 将需要使用metaclass来构建class的类的__metaclass__属性(不需要显示声明,直接有的了)赋值为函数metaclas_new
 
3 metaclass 原理
 
3.1 basic
 
metaclass的原理其实是这样的:当定义好类之后,创建类的时候其实是调用了type的__new__方法为这个类分配内存空间,创建
 
好了之后再调用type的__init__方法初始化(做一些赋值等)。所以metaclass的所有magic其实就在于这个__new__方法里面了。
 
说说这个方法:__new__(cls, name, bases, attrs)
 
cls: 将要创建的类,类似与self,但是self指向的是instance,而这里cls指向的是class
 
name: 类的名字,也就是我们通常用类名.__name__获取的。
 
bases: 基类
 
attrs: 属性的dict。dict的内容可以是变量(类属性),也可以是函数(类方法)。
 
所以在创建类的过程,我们可以在这个函数里面修改name,bases,attrs的值来自由的达到我们的功能。这里常用的配合方法是
 
getattr和setattr(just an advice)
 
3.2 查找顺序
 
再说说关于__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.
 
这个查找顺序也比较好懂,而且利用这个顺序的话,如果是old-style类的话,可以在某个需要的模块里面指定全局变量
 
__metaclass__ = type就能把所有的old-style 变成 new-style的类了。(这是其中一种trick)

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读