如何理解 Python 元类

01

“元XX” 这个组合相信很多同学都见过。比如“元知识”、“元数据”。元知识表示的是知识的知识。元数据表示的是数据的数据。比如有一本书叫做《如何阅读一本书》它的内容就是元知识,就是如何学习知识的知识。“元”这个词就是对某一事物更高层次的抽象。

02

所谓元类,就是类的类。也可以这么解释,对象是类实例化生成的,那类又是谁生成的?含无疑问,类是元类生成的。(我脑补的画外音: -->)大话西游里的唐僧被绑时,他对着旁边的小妖说的:人和妖精都是妈生的,不同的人是人他妈生的,妖是妖他妈生的……你妈贵姓啊?

03

在讨论Python的元类之前,先说一说Python的__new()__方法:

>>> class Person(object):
        def __new(cls, name, age):
            print('I am __new__')
            return object.__new__(cls, name, age)

首先执行使用name和age参数来执行Person类的__new__方法,这个__new__方法会 返回Person类的一个实例(通常情况下是使用 object.__new__(cls, … …) 这样的方式),也就是说在类被实例化之前提供给你一个自定义这些类的实例化过程的途径,返回一个实例化对象。

04

再说一说Python的type()函数,它有两种用法:

  • 测试对象的类型
>>> print(type(1))
<class 'int'>
>>> print(type('1'))
<class 'str'>
  • 动态创建类
>>> mc = type('MyClass',(),{})
>>> print(mc)
<class '__main__.MyClass'>
>>> print(mc())
<__main__.MyClass object at 0x0000000002EA8358>

重点注意的就是第二种用法,用来动态创建类。
type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值))

05

__metaclass__就是Python中的元类。

根据上文我们知道元类作用就是生成类,它的用法举例如下:

class ListMetaclass(type):
    def __new__(cls, name, bases, attrs):
        attrs['add'] = lambda self, value: self.append(value)  # 在MyList中添加了一个add方法
        return type.__new__(cls, name, bases, attrs)

class MyList(list):  
    __metaclass__ = ListMetaclass # 指示使用ListMetaclass来定制类

当我们定义MyClass时,Python做了如下的操作:

MyClass中查找是否有__metaclas__这个属性?如果有,Python会在内存中通过__metaclass__后自定义的类或者函数(本文中用的是ListMetaclass)创建一个名字为MyClass的类对象(我说的是类对象,请紧跟我的思路)。如果Python没有找到__metaclass__,它会继续在父类中寻找__metaclass__属性,并尝试做和前面同样的操作。如果Python在任何父类中都找不到__metaclass__,它就会在模块层次中去寻找__metaclass__,并尝试做同样的操作。如果还是找不到__metaclass__Python就会用内置的type来创建这个类对象。

现在的问题就是,你可以在__metaclass__中放置些什么代码呢?答案就是:可以创建一个类的东西。那么什么可以用来创建一个类呢?type,或者type的子类都可以。

06

但就元类本身而言,没什么好说的,它只做了三件事:

  1. 拦截类的创建(03)

  2. 修改类(05)

  3. 返回修改之后的类(04)

07

元类的实际用途有哪些?ORM就是一个典型的例子。
这个我就不多说了。具体可参考 廖大大的文章 。



作者:全栈coder
链接:https://www.jianshu.com/p/36e4a8aba0b1
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
posted @ 2019-07-20 10:18  天涯海角路  阅读(102)  评论(0)    收藏  举报