两句话掌握 Python 最难知识点——元类出处


两句话掌握 Python 最难知识点——元类出处

文章插图
 
每个中国人,都是天生的元类使用者
学懂元类,你只需要知道两句话:
  • 道生一,一生二,二生三,三生万物
  • 我是谁?我从哪来里?我要到哪里去?
在Python/ target=_blank class=infotextkey>Python世界,拥有一个永恒的道,那就是“type”,请记在脑海中,type就是道 。如此广袤无垠的python生态圈,都是由type产生出来的 。
道生一,一生二,二生三,三生万物 。
  1. 道 即是 type
  2. 一 即是 metaclass(元类,或者叫类生成器)
  3. 二 即是 class(类,或者叫实例生成器)
  4. 三 即是 instance(实例)
  5. 万物 即是 实例的各种属性与方法,我们平常使用python时,调用的就是它们 。
道和一,是我们今天讨论的命题,而二、三、和万物,则是我们常常使用的类、实例、属性和方法,用hello world来举例: 1
2
3
4
5
6
7
8
9
10
11
# 创建一个Hello类,拥有属性say_hello ----二的起源
class Hello():
def say_hello(self, name='world'):
print('Hello, %s.' % name)
# 从Hello类创建一个实例hello ----二生三
hello = Hello()
# 使用hello调用方法say_hello ----三生万物
hello.say_hello()
输出效果:
1
Hello, world.
这就是一个标准的“二生三,三生万物”过程 。 从类到我们可以调用的方法,用了这两步 。
那我们不由自主要问,类从何而来呢?回到代码的第一行 。
class Hello其实是一个函数的“语义化简称”,只为了让代码更浅显易懂,它的另一个写法是:
1
2
3
4
def fn(self, name='world'): # 假如我们有一个函数叫fn
print('Hello, %s.' % name)
Hello = type('Hello', (object,), dict(say_hello=fn)) # 通过type创建Hello class ---- 神秘的“道”,可以点化一切,这次我们直接从“道”生出了“二”
这样的写法,就和之前的Class Hello写法作用完全相同,你可以试试创建实例并调用
Python
1
2
3
4
5
# 从Hello类创建一个实例hello ----二生三,完全一样
hello = Hello()
# 使用hello调用方法say_hello ----三生万物,完全一样
hello.say_hello()
输出效果:
1
Hello, world. ----调用结果完全一样 。
我们回头看一眼最精彩的地方,道直接生出了二:
Hello = type(‘Hello’, (object,), dict(say_hello=fn))
这就是“道”,python世界的起源,你可以为此而惊叹 。
注意它的三个参数!暗合人类的三大永恒命题:我是谁,我从哪里来,我要到哪里去 。
  • 第一个参数:我是谁 。在这里,我需要一个区分于其它一切的命名,以上的实例将我命名为“Hello”
  • 第二个参数:我从哪里来
    在这里,我需要知道从哪里来,也就是我的“父类”,以上实例中我的父类是“object”——python中一种非常初级的类 。
  • 第三个参数:我要到哪里去
    在这里,我们将需要调用的方法和属性包含到一个字典里,再作为参数传入 。以上实例中,我们有一个say_hello方法包装进了字典中 。
值得注意的是,三大永恒命题,是一切类,一切实例,甚至一切实例属性与方法都具有的 。理所应当,它们的“创造者”,道和一,即type和元类,也具有这三个参数 。但平常,类的三大永恒命题并不作为参数传入,而是以如下方式传入
1
2
3
4
5
6
7
8
class Hello(object){
# class 后声明“我是谁”
# 小括号内声明“我来自哪里”
# 中括号内声明“我要到哪里去”
def say_hello(){
}
}