exec内置函数的补充
exec: 是一个python内置函数,可以将字符串的代码添加到名称空间中;
- 全局名称空间
- 局部名称空间
exec(字符串形式的代码, 全局名称空间, 局部名称空间)
# 使用exec, code相当于局部名称空间中的名字 code = ''' global x x = 100 y = 20 def func(): pass def __init__(): pass ''' # 自定义的全局名称空间 global_dic = { 'x': 10000 } # 自定义的局部名称空间 local_dic = { 'y':300 } # print(global_dic) # # print(local_dic) exec(code, global_dic, local_dic) print(global_dic) # {'x': 100, ...} 此处全局变量1000被code中x=100替换 # print(local_dic) # {'y': 20, 'func': <function func at 0x00000000003D1E18>, '__init__': <function __init__ at 0x00000000023789D8>} # 局部空间y=300被code中y=20替换
元类
1.什么是元类?
- 类的类就是type, 其实type就是元类;
2.元类的作用?
- 元类可以控制类的创建过程!
3.如何创建元类以及使用?
# 1.一切皆对象 list1 = [] # list1 = list([]) # print(type(list1)) # <class 'list'> # 2.自定一个类 class Chinese(object): country = 'china' def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex p_obj = Chinese('tank', 17, 'male') # print(type(p_obj)) # <class '__main__.Chinese'> print(Chinese) # 类本质上也是一个对象,因为在python中 一切皆对象 ; # print(type(Chinese)) # <class 'type'> 说明Chinese类是有type实例化的对象
# 3.如何产生类的: # 1) 通过class关键字产生类 # 2) 通过调用type类: type() ---> obj ---> Chinese # what: 指的是类名 # bases: 继承的父类 (object, ) # dict: 类的名称空间 code = ''' country = 'china' def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex ''' # class_attr class_attr = {} exec(code, {}, class_attr) # type(类的名字, 类的基类, 类的名称空间) ----> 类 ---> 对象 obj = type('Chinese', (object, ), class_attr) # def __init__(what, bases=None, dict=None) # print(obj) Chinese = obj print(Chinese) # <class '__main__.Chinese'> chinese_obj = obj('tank',18,'male') print(chinese_obj.country) # china
1.什么是元类?
类的类就是type, 其实type就是元类;
2.为什么要使用元类???
元类可以控制类的创建过程!
# type是python内置的元类 # 自定义一个元类 class MyMetaClass(type): # 控制类的创建 # 优酷需要用到的部分; def __init__(self, class_name, class_bases, class_dict): # self, obj print(type(class_name)) # print(class_name.istitle()) if not class_name.istitle(): raise NameError('类的首字母必须大写!') if not class_dict.get('__doc__'): raise TypeError('必须给我写注释!!!') # 必须将类中的类名、类的基类、类的名称空间,一并返回给 type中的__init__ super().__init__(class_name, class_bases, class_dict) # 了解: 元类更深层次的作用 # 控制调用类的行为 # 为什么调用类就一定会产生一个空对象,为什么一定会执行__new__ # 其实就是type内部一定会调用一次__call__,由__call__来帮你调用__new__。 # 元类中的__call__就是创建类的过程!!! def __call__(self, *args, **kwargs): print(args) # Foo类括号中的值 # 1.造一个空对象obj obj = object.__new__(self) # 创造一个空的对象 # self ---> User print(obj.__dict__, 1111111) # 2.调用类时,__call__会立马调用User.__init__, 并且将obj连同Foo括号内的参数一同传给__init__ self.__init__(obj, *args, **kwargs) # return一个真正创建的对象 return obj # obj = MyMetaClass() # obj() # obj() ----> User(10, 20) ----> user_obj # 被控制类在定义阶段 类名(metaclass=自定义的元类) ---> 会将当前类的 # 1)类名、2)基类、3)类的名称空间 一并 传给 自定义的元类 # metaclass ---> 自定义的元类 ---> 调用自定义的元类(类名, 基类, 类的名称空间) # type(类名, 基类, 类的名称空间) class User(object, metaclass=MyMetaClass): # MyMetaClass(User, (object, ), {'x':10}) '''tank是真的很帅啊,真的舍不得你们啊!!!''' def __init__(self): pass x = 10 obj = User() print(obj)
'''
<class 'str'>
()
{} 11111111
<__main__.User object at 0x000000000258C4E0>
'''
属性查找顺序
class Mymeta(type): # 但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类 # n=444 def __call__(self, *args, **kwargs): #self=OldboyTeacher这个类 # 1. 先产生一个空对象 tea_obj = self.__new__(self) # tea_obj是OldboyTeacher这个类的对象 # print(self.__new__ is object.__new__) # tea_obj=object.__new__(self) # 2. 执行__init__方法,完成对象的初始属性操作 self.__init__(tea_obj, *args, **kwargs) # 3. 返回初始化好的那个对象 return tea_obj class Bar: # n = 33 pass class Foo(Bar): # n = 222 pass class OldboyTeacher(Foo, metaclass=Mymeta): # OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...}) # n = 111 school = 'Oldboy' def __init__(self, name, age, sex): self.name = name #None.name='egon' self.age = age self.sex = sex def score(self): print('%s is scoring' % self.name) def __new__(cls, *args, **kwargs): # print('=====>') return super().__new__(cls) tea1 = OldboyTeacher('egon', 18, 'male') # print(tea1) print(tea1.__dict__) # print(OldboyTeacher.n) # print(object.__new__)
图示顺序: