metaclass
除了使用type()动态创建类以外,要控制类的创建行为,还可以使用metaclass元类。
当我们定义了类以后,就可以根据这个类创建出实例,所以:先定义类,然后创建实例。
如果想创建类,就得用metaclass,先定义metaclass,然后创建类。
连接起来:先定义metaclass,创建类,最后创建实例。
metaclass允许你创建类 或者修改类,可以把类看成是metaclass创建出来的实例。
__init__是实例对象创建完成后被调用的,然后设置对象属性的一些初始值。
__new__是在实例创建之前被调用的,因为它的任务就是创建实例然后返回该实例,是个静态方法
也就是,__new__在__init__之前 被调用,__new__的返回值(实例)传递给__init__方法的第一个参数,然后__init__给这个实例 设置一些参数。
__new__至少要有一个参数cls,代表要实例化的类,此参数在 实例化时由python解释器自动提供
__new__必须要有返回值,返回实例化出来的实例,可以return父类__new__出来的实例,或者直接object的__new __出来的实例
__init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值
这一段参考 :https://blog.csdn.net/qq_41020281/article/details/79638370
例:给自定义的Mylist增加一个自定义的add方法
#定义Listmetaclass,按照默认习惯,metaclass的 类名总是以Metaclass来定制类,以便清楚地表示这是一个metaclass
#metaclass是类的模板 ,所以必须从‘type’类型派生
class ListMetaclass(type):
def __new__(cls, name, bases, attrs): #至少要有一个参数cls
attrs['add'] = lambda self, value:self.append(value) #这个类里面有add方法
return type.__new__(cls, name, bases, attrs)
#有了ListMetaclass,我们在定义类的时候还要指示使用ListMetaclass来定制类,传入关键字参数metaclass
class MyList(list, metaclass= ListMetaclass):
pass
当传入关键字参数metaclass的时候,魔术就生效了,它指示Python解释器在创建MyList时,要通过 ListMetaclass.new()来创建,在此,我们可以修改类的定义,比如,加上新的方法,然后返回修改后的定义。
__new__()
方法接收到的参数依次是:
1.当前准备创建的类的对象;
2.类的名字;
3.类继承的父类集合;
4.类的方法集合。
测试一下MyList是否可以调用add()方法:
L = MyList()
L.add(1)
print(L)
输出:
[1]
通常直接在MyList上加add()方法是更简单,但会遇到需要通过metaclass修改类定义的,ORM就是典型的例子。
ORM全称‘Object Relational Mapping’,即对象-关系模型,就是把关系数据库的一行映射为 一个对象,也就是一个类对应一个表,这样写代码更简单,不用直接操作 SQL包。
要编写一个ORM框架,所有的类都只能动态定义,因为只有使用者才能根据表的结构定义处对应的类来。
让我们来尝试编写一个ORM框架
编写低层模块的第一步 ,就是先把调用接口写出来。比如,如果使用者使用这个ORM框架,想定义一个User类 来操作对应的数据库表User,我们期待他写出这样的代码:
class User(Model):
#定义类的属性到列的映射:
id = IntegerField('id')