元类
引入
一切都源自于一句话:一切皆为对象
如何得到对象
或者叫实例化
obj=调用类()
函数,模块,类本身都是对象
如果说类也是对象
class People:
def __init__(self,name,age):
self.name=name
self.age=age
def say(self):
print('%s:%s' %(self.name,self.name))
# People=调用类(。。。)
什么是元类
# 元类就是用来实例化产生类的类
# 关系:元类---实例化---->类(People)---实例化---->对象(obj)
# 查看内置的元类:
# 1、type是内置的元类
# 2、我们用class关键字定义的所有的类以及内置的类都是由元类type实例化产生
# print(type(People)) # <class 'type'>
# print(type(int)) # <class 'type'>
class机制分析
class关键字到底是怎么把类创造出来的?
类的三大特征
拿到类名
拿到基类
运行类体代码,拿到类的名称空间
# 类有三大特征:
# 1、类名
class_name="People"
# 2、类的基类
class_bases=(object,)
# 3、执行类体代码拿到类的名称空间
# 类的名称空间
class_dic={}
# 类体代码
class_body="""
def __init__(self,name,age):
self.name=name
self.age=age
def say(self):
print('%s:%s' %(self.name,self.name))
"""
定义类的时候,类体代码会立即运行
运行过程中会把产生的类的名字放到名称空间里面去,
名称空间是一个字典
所以,类体放的是一个字符串,执行类体代码拿到类的名称空间
exec会执行类体代码,运行过程当中,会将产生的名字丢到class_dic中去
exec(class_body,{},class_dic)
print(class_dic)
# {'__init__': <function __init__ at 0x000002961A3D2EA0>, 'say': <function say at 0x000002961A5AAB70>}
最后一步,class机制会调用元类
# 在造类时,没有指定元类,就用默认元类type
People=type(class_name,class_bases,class_dic) # 传三个参数
# class造类的执行过程
class_name="People"
class_bases=(object,)
class_dic={}
class_body="""
def __init__(self,name,age):
self.name=name
self.age=age
def say(self):
print('%s:%s' %(self.name,self.name))
"""
exec(class_body,{},class_dic)
print(class_dic)
People=type(class_name,class_bases,class_dic)
print(People) # <class '__main__.People'>
# 可以正常使用
obj = People('xiaoming',18)
print(obj.__dict__) # {'name': 'xiaoming', 'age': 18}
# 学习了class机制底层的4个步骤,可以对哪些步骤进行操作
# 前三步骤没啥好操作的,都是最终交给内置元类type进行实例化
# 咱们要想方设法自定制元类,进而控制类的生成
People=Mymeta(class_name,class_bases,class_dic)