Python中type和元类的用法
我们知道 Python 是动态语言,动态语言和静态语言最大的不同就是函数和类的定义,在动态语言中函数和类的定义不是编译时产生的,而是在运行时动态创建的,所以我们就没必要先定义好一个类,我们可以在代码的任何地方根据需要来随时的定义类,Python的 type 和 metaclass 可以帮我们动态创建一个类。
type 是 Python 内置的函数对象类,这个类很特殊,我们可以把他当做函数来看待,
我们查看 type 类的源码,发现他的构造函数的声明为: type(object) -> the object's type
, type(name, bases, dict) -> a new type
。也就是说当给它传入一个参数时,它返回这个参数所属的类型;
当传入三个参数时,它返回一个新的类型(大家可以认为是一个新的类),这样我们就可以用这个类来创建对象了。
metaclass 是元类,我们可以使用 metaclass 创建出类,然后根据这个类创建对象,这就和用 type 实现一样的效果。
使用 type 创建类
要使用 type 创建一个类,我们需要对 type 类构建的对象依次传入3个参数: class的名称,继承的父类集合(可以继承多个父类,是个 tuple类型),class 的方法名称与函数绑定。比如下面的例子我们把函数 func 绑定到方法名 Human 上。
def func(self, name): # 在类之前定义要绑定的函数 print("I'm " + name) Human = type('Human', (object,), {"talk": func}) # 创建 Human 类,该类继承 object,有一个talk函数 ruhua = Human() ruhua.talk("ruhua")
通过 type 函数创建的类和直接写 class 定义的类是完全一样的,实际上 Python 解释器遇到 class 定义时,仅仅是扫描一下class 定义的语法,然后调用 type 函数创建出 class。 我们在使用 type 创建类时,完全可以后期动态绑定函数和属性,要注意给类动态绑定和给类的对象动态绑定的区别。
def func(self): # 在类之前定义要绑定的函数 print(u"我是类绑定的") def func2(): print(u"我是某个对象绑定的") Human = type('Human', (object,), {}) Human.func = func Human.data = "我是类的属性" ruhua = Human() ruhua.func2 = func2 ruhua.data2 = "我是某个对象的属性" ruhua.func() # 正确 print(ruhua.data) # 正确 ruhua.func2() # 正确 print(ruhua.data2) # 正确 zhaoritian = Human() zhaoritian.func() # 正确 print(zhaoritian.data) # 正确 zhaoritian.func2() # 错误 print(zhaoritian.data2) # 错误
使用 metaclass 创建类
除了使用 type 动态创建类以外,还可以使用 自己定义的元类(metaclass)来创建类, 自己定义一个元类,首先该类要继承 type 类,我们还需要定义一个 __new__ 函数, __new__ 函数接收到的参数依次是:当前准备创建的类的对象,类的名字,类继承的父类集合,类的函数集合。 我们在使用 metaclass 创建类,按照默认习惯,metaclass 的类名总是以 Metaclass 结尾,以便清楚地表示这是一个 metaclass。
class MyObjectMetaclass(type): def __new__(cls, name, bases, funcs): def setdata(self, value): self.data = value funcs['setdata'] = setdata return type.__new__(cls, name, bases, funcs) class MyObject(object, metaclass=MyObjectMetaclass): pass myobject = MyObject() myobject.setdata("hello") print(myobject.data)
在我们项目开发中,我们几乎不会用到本节课所讲的知识,但在阅读其它源码时,我们碰到这种语法要看的明白(下个阶段我们要学习的 web 开发中,orm 的 model 设计经常用到这种语法),大家注意,Python 这种语言很自卑,语言也像人一样,自卑的人都想弄点奇技淫巧,找到机会就装逼,metaclass就是个很好的例子。
本节重要知识点
看的明白 type 创建类的语法。
看的明白使用元类的语法。
评论列表