本文始发于个人公众号: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面试常用的高级用法,怎么动态创建类?的更多相关文章

  1. 使用python type动态创建类

    使用python type动态创建类 X = type('X', (object,), dict(a=1))  # 产生一个新的类型 X 和下列方法class X(object):    a = 1效 ...

  2. Python中type()详解:动态创建类

    众所周知: type()函数可以查看变量的类型: 先看一个简单的列子来看一下type查看变量类型 class Animal(): pass a=Animal() print(type(a)) prin ...

  3. python动态创建类的声明

    动态创建类的声明 使用内置函数type,原型:class type(name, bases, dict)name是类的名字,相当于__class__bases是类的基类,元组,可以有多个基类,但是基类 ...

  4. Python 中使用动态创建类属性的机制实现接口之后的依赖

    我们在自动化测试中经常会需要关联用例处理,需要动态类属性: 推荐使用第二种方法: 创建:setattr() 获取:getattr() 两种,如何创建 类属性 loan_id # 第一种,创建 # 类名 ...

  5. python-获取类名和方法名,动态创建类和方法及属性

    获取类名和方法名1.在函数外部获取函数名称,用.__name__获取2.在函数内部获取当前函数名称,用sys._getframe().f_code.co_name方法获取3.使用inspect模块动态 ...

  6. ios动态创建类Class

    [Objective-C Runtime动态加载]---动态创建类Class 动态创建类Class,动态添加Class成员变量与成员函数,动态变量赋值与取值,动态函数调用等方法 a.使用objc_al ...

  7. OC 反射-->动态创建类

    系统方法 NSLog(@"%s", __func__); //打印出类的方法名称,如: //打印结果:2018-02-22 10:52:15.394575+0800 DemoRun ...

  8. type动态创建类

    在一些特定场合,需要动态创建类,比如创建表单,就会用到type动态创建类,举个例子: class Person(object): def __init__(self,name,age): self.n ...

  9. 动态创建类/ swizzle class

    动态创建类 Class subclass = objc_allocateClassPair(baseClass, subclassName, );//生成,指定父类 //添加方法,变量...一些操作 ...

随机推荐

  1. shell脚本命令 运行python文件&python命令行运行python代码

    单独的python文件运行的时候 报错: 在shell脚本中,运行shell脚本命令:在Python命令行中,运行Python代码.然而,“python hello.py”是一个脚本命令,不是pyth ...

  2. post请求导出表单。

    postExcelFile(params, url) { //params是post请求需要的参数,url是请求url地址 var form = document.createElement(&quo ...

  3. Redis学习笔记(十) 客户端

    Redis服务器是典型的一对多服务器程序:一个服务器可以与多个客户端建立网络连接,每个客户端可以向服务器发送命令请求,而服务器则接收并处理客户端发送的命令请求,并向客户端返回命令回复. 通过使用由I/ ...

  4. Java的泛型详解(一)

    Java的泛型详解 泛型的好处 编写的代码可以被不同类型的对象所重用. 因为上面的一个优点,泛型也可以减少代码的编写. 泛型的使用 简单泛型类 public class Pair<T> { ...

  5. React框架概述

    一.React框架概述 官网:https://reactjs.org/       最新版V16.10 中文网:https://zh-hans.reactjs.org/ 中文社区网:https://r ...

  6. MySQL执行外部sql脚本文件命令是报错:unknown command

    使用source导入外部sql文件: mysql> source F:\php\bookorama.sql; -------------- source F: -------------- ER ...

  7. 【漫画】ES原理 必知必会的倒排索引和分词

    倒排索引的初衷 倒排索引,它也是索引.索引,初衷都是为了快速检索到你要的数据. 我相信你一定知道mysql的索引,如果对某一个字段加了索引,一般来说查询该字段速度是可以有显著的提升. 每种数据库都有自 ...

  8. SpringBoot瘦身

    1.介绍 本教程中,我们将研究如何使用spring-boot-thin-launcher项目来将Spring Boot项目瘦身. Spring Boot出了名的把所有依赖打包成单个可执行的Fat JA ...

  9. 【python爬虫】解决歌荒,下歌利器

    python下载图片,mp3,想必很多人都早已耳闻,今天给大家来点不一样的, 让你下载高逼格高品质,带进度条,实时显示下载速度 详见源码:https://www.kesci.com/home/proj ...

  10. SQL——MySQL数据类型

    Text类型: Number类型: Date类型: