Skip to content

Latest commit

 

History

History
131 lines (82 loc) · 3.6 KB

3.md

File metadata and controls

131 lines (82 loc) · 3.6 KB

三、什么是元类

通过上面的介绍,终于模模糊糊的带到元类这里来了。可是我们到现在还不知道元类是什么鬼东西。

我们创建类的时候,大多数是为了创建类的实例对象。

那么元类呢?

元类就是用来创建类的。也可以换个理解方式就是:元类就是类的类。

通过上面 type() 函数的介绍,我们知道可以通过 type() 函数创建类:

MyClass = type('MyClass', (), {})

实际上 type() 函数是一个元类。

type() 就是 Python 在背后用来创建所有类的元类。

那么现在我们也可以猜到一下为什么 type() 函数是 type 而不是 Type呢?

这可能是为了和 str 保持一致性,str 是用来创建字符串对象的类,而 int 是用来创建整数对象的类。

type 就是创建类对象的类。

你可以通过检查 __class__ 属性来看到这一点。

Python 中所有的东西,注意喔,这里是说所有的东西,他们都是对象。

这包括整数、字符串、函数以及类。它们全部都是对象,而且它们都是从一个类创建而来。

# 整形
age = 23
print(age.__class__)
# 字符串
name = '两点水'
print(name.__class__)


# 函数
def fu():
    pass


print(fu.__class__)


# 实例
class eat(object):
    pass


mEat = eat()

print(mEat.__class__)

输出的结果如下:

<class 'int'>
<class 'str'>
<class 'function'>
<class '__main__.eat'>

可以看到,上面的所有东西,也就是所有对象都是通过类来创建的,那么我们可能会好奇,__class__ 的 __class__ 会是什么呢?

换个说法就是,创建这些类的类是什么呢?

我们可以继续在上面的代码基础上新增下面的代码:

print(age.__class__.__class__)
print(name.__class__.__class__)
print(fu.__class__.__class__)
print(mEat.__class__.__class__)

输出的结果如下:

<class 'type'>
<class 'type'>
<class 'type'>
<class 'type'>

认真观察,再理清一下,上面输出的结果是我们把整形 age ,字符创 name ,函数 fu 和对象实例 mEat 里 __class__ 的 __class__ 打印出来的结果。

也可以说是他们类的类打印结果。发现打印出来的 class 都是 type 。

一开始也提到了,元类就是类的类。

也就是元类就是负责创建类的一种东西。

你也可以理解为,元类就是负责生成类的。

而 type 就是内建的元类。也就是 Python 自带的元类。

先分清对象与类,再看创建类的工具

这一章容易让人绕进去,因为我们不只在创建实例,还在讨论类本身。先用三个判断把关系摆出来:

StudyRecord = type('StudyRecord', (), {'category': '学习记录'})
record = StudyRecord()
print(type(record) is StudyRecord)
print(type(StudyRecord) is type)
print(record.category)

输出:

True
True
学习记录

第一行创建一个类,第二行再用这个类创建实例。type(record) 观察实例属于什么类,type(StudyRecord) 则继续观察类本身的类型。在这个普通例子里,类由 type 创建。

自己用 class StudyRecord: 写出对应版本,给它同样的 category,再比较这三个结果。先把两种创建方式的对应位置看明白,再回看自定义元类在创建过程中的作用。

元类属于进阶内容。初次学习如果暂时用不上,可以完成关系对照后继续后面的课程,带着「创建一个类时还能做什么」这个问题回来。它不是完成普通函数、脚本和综合项目的前提。