《老鸟python 系列》视频上线了,全网稀缺资源,涵盖python人工智能教程,爬虫教程,web教程,数据分析教程以及界面库和服务器教程,以及各个方向的主流实用项目,手把手带你从零开始进阶高手之路!点击 链接 查看详情




type和元类

阅读:227568523    分享到

我们知道 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 创建类的语法。

看的明白使用元类的语法。

作业

思考一下动态给类绑定属性和动态给对象绑定属性和我们自己定义的类中如何定义属性的方式一样。


如果以上内容对您有帮助,请老板用微信扫一下赞赏码,赞赏后加微信号 birdpython 领取免费视频。


登录后评论

user_image
Narc
2020年7月24日 06:34 回复

那么问题来了,为什么需要元类呢?它有什么不可替代的地方呢?


user_image
Maxbin
2020年4月24日 14:05 回复

非常恰当的描述


user_image
蓝色
2020年3月1日 09:39 回复

还有object吧,好像type是继承object的。到底什么时候用type, 什么时候用object?


user_image
David-Lau
2019年11月14日 21:30 回复

写的很不错,给赞!


user_image
活在当下
2019年8月9日 08:19 回复

支持。虽然我只是初学,不太懂。但是觉得给我描绘了python的整体图景。让我又了更清晰的认识


user_image
王大喵
2019年7月11日 17:17 回复

python中的哲学


user_image
李国宝
2019年2月15日 21:54 回复

写的很不错! 但是一直有个问题,如果要去描述类之间的关系,比如用UML这类工具,那么元类与实现它的类应该算做什么关系呢