1>元类的概念
1.1> 知识储备只回顾exec方法,看一下它的三个参数
参数1:object是一个字符串的语句或者一个编译过的语句的对象名称;
参数2:全局作用域(字典形式),globals 是个 dict 对象,用来指定代码执行时可以使用的全局变量以及收集代码
执行后的全局变量,如果不指定默认就使用globals();
参数3:局部作用域(字典形式),locals 可以是任何 mapping 对象,用来指定代码执行时的局部变量以及收集代码
执行后的局部变量,如果不指定默认就使用locals()。
例子
1.2> 说一说何为“python的一切皆对象”,对象可以怎么用
1、都可以被引用,x=obj
2、都可以当作函数的参数传入
3、都可以当作函数的返回值
4、都可以当作容器类的元素,l=[func,time,obj,1]
那么,站在类的角度(比如就手动用 class定义一个类),类也满足上面的4点,是否类 也是一个对象?例子如下:
此时的 type就是 元类。所有以 class定义的类都是以type为模板创建出来的,他们都是type实例化的对象
所以,元类其实就是类的类,类的模板,class的元类就是type。
type是python的一个内建元类,用来直接控制生成类
2>创建类的两种方式
2.1> 用class定义一个类,如 class A():pass,这就定义了一个类A
2.2> 是手动模拟class创建类的过程:将创建类的步骤拆分开,手动去创建
创建之前,先看下类的组成:类名(毫无疑问,这个肯定要有),继承的父类(就算不写也会默认继承object,
所以这项一定有),类的实体----也就是类的命名空间,定义类的时候,类里面的所有属性都会以字典形式存放
在一个局部的名称空间里面,可以用__dict__查看这些属性。
2.2.1>所以一个类应该就是由这么三部分组成,基于之前提到的exec方法,我们搞定 类的实体,也就是想办法
模拟产生一个类的实体。
exec去执行类体的代码(exec产生名称空间的过程与真正的class过程类似,只是后者会将__开头的属性变形),
生成类的局部名称空间,即填充字典。
2.2.2>调用元类type(或者自定义的元类),来产生类A
3>自定义元类来控制类的行为
一个类没有声明自己的元类,默认他的元类就是type,除了使用元类type,用户也可以通过继承type来自定义元类
从需求开始:比如我想在创建类的时候,指定类名的首字母必须大写,且必须写注释,否则创建类的时候就报错。
既然是要规范类行为,那么就只能去改 创建类的时候他继承的模板了,对吧
恩, 那就创建一个元类,创建之前,再回忆下之前通过元类实例化类的时候需要的参数
例如,假设我定义好了元类 Myclass,那么 创建类就是 A = Myclass('A', (object, ), class_dic),有三个参数哈
所以,很明显,Myclass就该有三个参数:类名,基类,名称空间, 具体如下
有三个参数,继承至type的参数,并且自定义了规则,这样便实现了通过元类来控制类的行为