社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Python面试常用的高级用法,怎么动态创建类?

承志 • 5 年前 • 532 次点击  
阅读 40

Python面试常用的高级用法,怎么动态创建类?

本文始发于个人公众号:TechFlow,原创不易,求个关注


今天是Python专题的第16篇文章,今天我们来聊聊Python当中的元类。

元类是Python当中的高级用法,如果你之前从来没见过这个术语或者是没听说过这个概念,这是非常正常的,因为一方面它的使用频率不高,另外一方面就是它相对不太容易理解。以至于很多Python开发者都理解得不是很深入,导致了市面上相关的资料也并不太多。我也是读了一些大牛的代码才开启了这扇新世界的大门。

一切都是对象

我们之前的时候曾经介绍过,在Python当中一切都是对象,注意,是一切都是对象。我们都知道对象是类实例化之后的结果,可以简单地将类和对象类比成模具和成品的关系。模具是类,而根据模具做出来的产品是对象。

这个比喻思想比较接近,但是不完美。因为实际当中一个模具可以做出多个产品,一个产品只有一个模具。但编程语言当中不同,由于类之间可以继承以及多继承,也就是说一个对象可以对应多个类。所以这个比喻不是特别合适,但是类和对象的关系是没错的。

但是这就有了一个问题,既然Python当中一切都是对象,那么是不是说类其实也是一个对象呢?也就是说一个模具其实也是另外一个模具的产品?同样,这个模具的模具其实也是另外一个模具的产品,那么我们一直追问下去会怎么样呢?

很简单,我们做个实验就知道了,我们可以用_class__关键字来查看一个变量的类型,那么我们反复调用就可以查看其中的关系了:

从上面的图中我们可以发现,num是int类型的变量。我们继续查看int这个类型的类型,得到了type类型。而当我们去查看type的类型的时候,会发现我们得到的还是一个type的类型。

所以我们可以明白了,type是Python中用来创建所有类的元类,是所有模具的模具。在Python当中,我们把一个类的类叫做元类(metaclass)。所以type就是Python当中内置的元类,我们也可以自己创建我们需要的元类。通过元类,我们创建的对象也是一个类,而不是一个实例。

动态创建类

理解了type是一切类基础之后,再来看动态类就简单了。动态类是动态语言最大的特性之一,作为典型的动态语言,Python自然也是支持类型的动态创建的。

在Python当中,创建动态类型的一种方式就是通过type关键字。说起来有些意想不到,type函数不是用来查询对象所属的类型的吗,怎么还可以创建类呢?

这其实是type的另外一种用法,作为元类来创建一个类。在这种用法,type函数接收3个参数,分别是类型的名称,父类的元组,以及一个字典。除了第一个参数之外,后面两个参数都可以为空。比如我们来看一个例子:

注意,type返回的结果是一个类,而不是一个实例。所以我们还可以通过它创建实例:

hello = Hello()
复制代码

这样创建出来的是最简单的空类,它什么也没有,和下面的代码等价。

class Hello:
    pass
复制代码

我们也可以在type的参数当中为这个类填充属性和方法:

def hello_world(self):
    print('hello')
    
Hello = type('Hello', (), {'hello'


    
:hello_world, 'num': 3})
复制代码

这样我们就为Hello这个类创建了一个方法叫做hello,一个属性num等于3。我们可以来调用一下试试:

也就是说我们可以使用type来根据我们的需要自行定义类,只不过type既可以获取对象的类型又可以创建新的类,看起来可能觉得有些不太直观,但是其实这也是说得通的。我们在Python当中通过调用str创建一个string对象,通过int来创建一个integer对象,那么通过type则是创建一个类的对象。

实现继承

我们之前说了,当我们使用type来创建类的时候,还可以传入父类的元组从而实现类的继承。

比如我们再创建一个叫做World的类继承刚才通过type创建出来的Hello类,然后在为它加上额外的函数:

def say_world(self):
    print('World')
    
World = type('World', (Hello, ), {'world': say_world})
复制代码

注意这里传入第二个参数是父类的元组,既然是元组,那么当元素只有一个的时候,需要加上逗号,表示这是一个元组。这样创建出来的类和我们通过class定义的静态类效果是一样的:

也就是说,我们可以先把函数实现,然后再根据任务的需要把这些函数组装成新的类。显然,这和传统的C++以及Java这些静态类型的语言相比,要灵活得多。

总结

我们固然可以通过type来创建动态创建类,但是从上面的使用过程也应该看得出来,这样使用起来并不太方便,并且很多进阶的功能很难实现。举个简单的例子,比如我们想要动态地为一个已有的类添加一些动态的方法,生成新的类。我们使用type就很难实现。type也的确不是Python元类的主要运用,metaclass才是王道,但由于篇幅限制,这部分将放在下一篇文章当中。

当然,元类是一个非常高级的用法,以至于Python的创始人说99%的Python程序员并不需要用到它。所以如果你觉得理解起来非常费劲的话也没有关系,知道这么个概念就可以了。

今天的内容就是这些,如果喜欢本文,可以的话,请点个关注,给我一点鼓励,也方便获取更多文章。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/64307
 
532 次点击