python元类浅析

声明:本文仅限于简书发布,其他第三方网站均为盗版,原文地址: python元类浅析

在 python 的新式类中,元类可能是最难以理解的功能之一了,不仅元类这个概念难以理解,而且很多讲解和阐述也是说得云里雾里,我看过很多很多篇关于元类和 metaclass 的介绍,但是依旧不是很懂,知道我硬着头皮看了两篇官方的解析之后,才有点理解了,本文我将尝试以一个比较简单的角度来介绍元类,希望不会像我看过的文章一样让读者也在云里雾里。

什么是元类

可能我们在学习 Python 的过程中,我们经常会听过一个概念,那就是“在Python 中,一切都是对象”,那么类呢?类也是对象么?是的,类也是对象,那么类既然是对象的话,它是谁的对象?

这个概念可能有点拗口,但是,事实上类是元类的对象,也就是类的类。元类的实例是类,类的实例是对象,就这么简单,我们可以这么验证:

奇怪了对吧,对于 3 中的 a 的类型是 A,我们毫无异议,但是 A 的类型是 type 是什么回事,那我们就反推一下,是不是可以这么理解:

对,就是这么理解,我们称 a 是类 A 的对象,那么,我们也要称 A 是 type 的对象,那么我们就可以将这里的 type 理解为类的类,也就是大家所说的 元类 了。根据 Python 的官方文档[3],完整的构造形式是这样的:

A = type('A', (object, ), dict({}))

class type(name, bases, dict)
With one argument, return the type of an object. The return value is a type object and generally the same object as returned by object.class.

The isinstance() built-in function is recommended for testing the type of an object, because it takes subclasses into account.
With three arguments, return a new type object. This is essentially a dynamic form of the class statement. The name string is the class name and becomes the __name__ attribute; the bases tuple itemizes the base classes and becomes the __bases__ attribute; and the dict dictionary is the namespace containing definitions for class body and is copied to a standard dictionary to become the __dict__ attribute. For example, the following two statements create identical type objects:

元类何时用

虽然,刚才演示的是用 type 来构造类,但是,这并不是 Python 的常用用法,因为这种用法比较麻烦,而且局限性比较大。既然是类的类,我们从上面看到,他可以创建类,那么,能不能不创建类,而只修改类的属性呢?事实上,Python 是可以的,根据 Python 官方文档[4] 所描述,默认情况下,类似通过 type() 来构建的;但是我们也可以通过在定义类的时候指定 metaclass 参数,来修改类的创建过程:

如何确定元类

可能你会奇怪,还需要知道如何确定元类?一个类的元类不是很明确吗?不一定哦,就以我们上面一个例子来说,我们可以很明确知道 MyClass 的元类是 Meta,那么 MySubclass 的元类呢?好像一下子不能肯定得答上来,下面再看看别人怎么说,还是参考文档[4]

The appropriate metaclass for a class definition is determined as follows:

  • if no bases and no explicit metaclass are given, then type() is used
  • if an explicit metaclass is given and it is not an instance of type(), then it is used directly as the metaclass
  • if an instance of type() is given as the explicit metaclass, or bases are defined, then the most derived metaclass is used

根据这些规则,我们就可以清晰得知道,我们的 MySubclass 的元类就是 Meta,基于的是第三条规则!

元类怎么用

和 type 一样,其实我们刚才也看到了,元类定义的时候通常传递三个参数,分别是:

  • 类名
  • 从基类继承数据的元素
  • 属性字典

这里再举个很简单的例子:

15039763574338

都不用创建实例,只需要定义一个类,我们就可以看到一些输出:

这就是元类,可以发现元类是传递了三个参数,分别是:类名/基类列表和属性字典。

元类实战

那么,元类到底有什么用呢?用处其实有很多,我就不自己写实例了,不然可能就会脱离实际,让大家说没有意义,要就来个实际的应用,就以 Flask 为例吧,看下 Flask 里面是如何应用 元类 的,我看的是 Flask 0.12.2 版本,这个版本里面只用了一处的 元类,那就是 View 类里面,代码为:

这里的用法比较奇特,它并没有用到我们上面提到的两种方法中的任何一种,反而是在 Line 9 中使用 type.new,构建了一个实例作为 MethodView 的父类,这种方法在参考资料 [5] 中作了详细介绍。之所以用这种方式,是因为这种方式更加 OOP,因为我们可以在之前的例子里面看到:

class MyClass(metaclass=Meta)

一点也不 OOP,因为无论是在 Java 中还是在 C++ 中,好像都没有说继承列表里面带参数名的吧?

Reference

  1. Core Python
  2. Understanding Python metaclasses
  3. Python Docs
  4. Customizing Class Creation
  5. What is a metaclass in Python?
  6. What is a metaclass in Python? 中文
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,776评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,527评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,361评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,430评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,511评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,544评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,561评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,315评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,763评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,070评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,235评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,911评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,554评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,173评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,424评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,106评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,103评论 2 352

推荐阅读更多精彩内容

  • 1.元类 1.1.1类也是对象 在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段。在Python中这...
    TENG书阅读 1,263评论 0 3
  • http://python.jobbole.com/85231/ 关于专业技能写完项目接着写写一名3年工作经验的J...
    燕京博士阅读 7,566评论 1 118
  • 让用户参与内容,帮助用户实现自我价值,通过互动产生内容,然后转换为产品的价值。就比如选秀节目,之前是专家打分,控制...
    猎人PENN阅读 171评论 0 0
  • 一直想为我爱了多年的偶像写点什么,不枉你们,如此惊艳我的时光。 回眸一笑,乱了浮生 初次见你,一场梨花雨下,你踏...
    浅月长安阅读 341评论 1 2
  • 腾哥 清华英语0A音频循环听,点读1本牛津。看了一集big muzzy, 三本中文书:昆虫记,我最好的朋友,上下五...
    疼福妈阅读 178评论 0 0