元类
元类
1、exec
exec是python内置函数,可以将字符串的代码添加到自定义的名称空间中
语法:exec(字符串形式的python代码,全局名称空间,局部名称空间)
字符串形式的代码是加载到自定义的名称空间中,可以在字符串名称空间中使用global将一些属性和方法引入自定义的全局名称空间中
名称空间是一个字典形式的
# 字符串形式的代码
code = '''
x = 10
y = 20
def func():
pass
def __init__():
pass
'''
# 自定义的全局名称空间
global_dic = {'z':100}
# 自定义的局部名称空间
local_dic = {'t':300}
print(global_dic)
print(local_dic)
exec(code,global_dic,local_dic)
print(code)
print(global_dic)
print(local_dic) # {'t': 300, 'x': 10, 'y': 20, 'func': <function func at 0x00000123A6602558>, '__init__': <function __init__ at 0x00000123A6602B88>}
2、元类
1、什么是元类
类的类就是type,type就是元类
type是python内置的元类
2、为什么要使用元类
元类可以控制类的创建过程,可以通过自定义的一个元类来控制创建的类的过程
3、怎么使用元类
# 自定义一个元类
class MyMetaClass(type):
# 控制类的创建,重写type中的__init__
def __init__(self, class_name, class_base, class_dict):
# 控制创建类时首字母必须大写
if not class_name.istitle():
raise NameError('类的首字母必须要大写!!')
# 控制创建类时必须要写注释
if not class_dict.get('__doc__'):
raise TypeError('定义必须要写注释!!')
# 必须要将重新定义__init__返回给type中的__init__
super().__init__(class_name, class_base, class_dict)
# 使用自定义元类(类名,基类,类的名称空间)来产生类
class User(object, metaclass=MyMetaClass):
'''
注释必须要写啊!
'''
def __init__(self):
pass
x = 10
# 调用类产生对象
obj = User()
print(obj)
为什么调用类就会产生一个空对象:内部执行了__ new__
为什么一定会执行__ new__:其实是type内部调用了一次__call__,由__call__来帮你调用__new__产生新的空对象,所有元类中的__call__ 就是创建类的过程
class MyMetaClass(type):
def __init__(self,class_name,class_base,class_dict):
if not class_name.istitle():
raise NameError('类定义必须首字母大写')
super().__init__(class_name,class_base,class_dict)
# 模拟__call__创建类的过程
def __call__(self,*args,**kwargs):
# 创造一个新空对象
obj = object.__new__(self)
# 调用类时,__call__会立马调用user.__init__,并且会将obj连同参数一并传入__init__
self.__init__(obj,*args,**kwargs)
# 返回一个真正的对象
return obj