在Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(’Class’)的概念。
类也是对象,可以把类看成是元类(’Metaclass’)创建出来的对象。
一、理解python中的class
在理解元类之前,你需要先掌握Python中的类。类同样也是一种对象
。是的,没错,就是对象。只要你使用关键字class,Python解释器在执行的时候就会创建一个对象。
|
|
通过以上片段我们可以知道,’s’是一个对象实例,而’S’是一个类。而通过type()我们可以查看它的类型:
|
|
可以看到s的类型是Class S
,而S的类型是type
,那么type是什么呢?
|
|
为什么class的类型是type??
二、理解type
动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的。
事实上,我们说class也是对象,而这个对象是运行时动态创建的,创建class的方法就是使用type()函数。
我们可以打印出help(type)
:
我们主要看type(name, bases, dict)
这个方法,事实上当我们定义class的时候,就是调用此方法来创建class对象的。
|
|
等价于
|
|
三、理解metaclass
metaclass,直译为元类,metaclass允许你动态的控制类的创建行为。换句话说,你可以把类看成是metaclass创建出来的“实例”。
因此我们可以先定义metaclass
,然后用metaclass创建类
,最后用类创建实例
。
我们先看一个简单的例子,这个metaclass可以给我们自定义的MyList增加一个add方法:
|
|
当我们传入关键字参数metaclass时,它指示Python解释器在创建MyList时,要通过ListMetaclass.__new__()
来创建,因此我们在__new__()
函数里面修改类的定义,比如,加上新的方法,然后,返回修改后的定义。__new__()
方法接收到的参数依次是:
- 当前准备创建的类的对象
- 类的名字
- 类继承的父类集合
- 类的方法集合
即:1234cls ==> `<class '__main__.ListMetaclass'>`name ==> `MyList`bases ==> (<class 'list'>,)attrs ==> {'__qualname__': 'MyList', '__module__': '__main__'}
当返回后,我们可以测试一下MyList类是否有add()方法:
动态修改类行为有什么意义?直接在MyList定义中写上add()方法不是更简单吗? 正常情况下,确实应该直接写,通过metaclass修改纯属变态。
但是,总会遇到需要通过metaclass修改类定义的。ORM就是一个典型的例子。ORM全称“Object Relational Mapping”,即对象-关系映射。
如果做过java web的同学应当知道,Hibernate
就是一个对象关系映射的框架。就是把关系数据库的一行映射为一个对象,也就是一个类对应一个表,这样,写代码更简单,不用直接操作SQL语句。
下一节,我们会学习如何用python来构建一个ORM框架。
References: