zoukankan      html  css  js  c++  java
  • 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, '
    
    
    
    ')
        print(func2, '
    
    
    
    ')
        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__。

    以上代码执行结果如下:

  • 相关阅读:
    斯特林反演
    子集计数
    快速求斯特林数总结(洛谷模板题解)
    min-25筛总结
    数学笔记
    [WC2018]即时战略(LCT,splay上二分)
    [WC2018]通道(乱搞,迭代)
    Python requests 多线程抓取 出现HTTPConnectionPool Max retires exceeded异常
    Python监控服务器利器--psutil
    gevent
  • 原文地址:https://www.cnblogs.com/csic716/p/12037040.html
Copyright © 2011-2022 走看看