CSIC_716_20191213【内置函数exec、元类】
In memory of the more than 300 thousand Chinese murdered
exec( 字符类型的代码,全局变量,局部变量 )。其中,全局变量和局部变量可以写成字典形式进行赋值。
举例:
''' 字符串 exec(字符串,全局变量、局部变量) ''' x = 10 expr = """ z = 30 sum = x + y + z print(sum) """ def func(): y = 20 exec(expr) exec(expr, {'x': 1, 'y': 2}) exec(expr, {'x': 1, 'y': 2}, {'y': 3, 'z': 4}) func()
exec关于局部名称空间和全局名称空间的关系,请参照以下例子: exec( 字符串格式是语句,全局名称空间,局部名称空间)
# _*_ coding: gbk _*_ # @Author: Wonder x = 10 expr = """ z = 30 y = 5 global x x = 18 m =10 print('x',x) print('z',z) sum = x + y + z print(sum) """ func1 = {'x': 1, 'y': 2} func2 = {'x': 3, 'y': 4} func3 = {'x': 99, 'y': 99} def func(): y = 20 x = 11 exec(expr) exec(expr, func1, func2) exec(expr, func3, func1) print(func1, '\n\n\n\n') print(func2, '\n\n\n\n') print(func3) func()
元类
元类是类的类,普通类是元类type的实例化对象,元类:type以及继承了type的类称为元类
元类实例化------>类,类实例化------>对象。
# _*_ coding: gbk _*_ # @Author: Wonder # 正常调用类 class Teach: def __init__(self, name, age): self.name = name self.age = age @property def bark(self): print('%s 别叫' % self.name) obj = Teach('dog', 18) print(obj) print(obj.name) obj.bark # 通过元类,生成类。type的三要素(class_name,class_bases, class_dict) class_dict = {} exec(''' def __init__(self, name, age): self.name = name self.age = age @property def bark(self): print('%s 别叫' % self.name) ''', globals(), class_dict) Teach2 = type('Teach', (object,), class_dict) obj1 = Teach2('horse', 17) print(obj1) print(obj1.name) obj1.bark
执行的结果如下:---->证明(两种方式都可以生成类)
定制元类,进行控制类的创建行为
# _*_ coding: gbk _*_ # @Author: Wonder class Mymeta(type): def __init__(self, class_name, class_bases, class_dict): ''' 此处可以对类名,类局部名称空间中的一些参数进行条件控制 :param class_name: :param class_bases: :param class_dict: ''' print('假装通过我,创造了类Teach') super().__init__(class_name, class_bases, class_dict) # 正常调用类 class Teach(object, metaclass=Mymeta): # Mymeta(class_name,class_bases,class_dict) def __init__(self, name, age): self.name = name self.age = age @property def bark(self): print('%s 别叫' % self.name) obj = Teach('dog', 18) obj.bark
需要注意的是,一定要写super().__init__(class_name, class_bases, class_dict) ,重用type生成类的功能
执行结果如下图,
定制元类,进行控制类的实例化行为
# _*_ coding: gbk _*_ # @Author: Wonder class Mymeta(type): def __init__(self, class_name, class_bases, class_dict): print('假装通过我,创造了类Teach') super().__init__(class_name, class_bases, class_dict) def __call__(self, *args, **kwargs): # 调用类,都会先触发__call__, 实例化的三部曲 # 1、造一个空对象 obj = object.__new__(self) # 2、初始化对象 self.__init__(obj, *args, **kwargs) # 3、返回一个对象 print('假装通过我来实例化对象') return obj # 正常调用类 class Teach(object, metaclass=Mymeta): # Mymeta(class_name,class_bases,class_dict) def __init__(self, name, age): self.name = name self.age = age @property def bark(self): print('%s 别叫' % self.name) obj = Teach('dog', 18) obj.bark
调用类,会触发__call__;用object.__new__ 造一个空对象 ;初始化对象时,空对象作为第一个参数传入__init__。
以上代码执行结果如下: