zoukankan      html  css  js  c++  java
  • 元类

    exec

    参数1:字串形式命令
    参数2:全局作用域(字典形式),如果不指定默认就使用globals()
    参数3:局部作用域(字典形式),如果不指定默认就使用locals()

    g = {"x":1,"y":2}
    l = {}
    exec('''
    global x,m
    x=10
    m=100
    z = 3''',g,l)     # 引号中产生一个变量,变量放到局部作用域中
    print(g)
    print(l)
    

      引号中产生一个变量,变量放到局部作用域中

    python中一切皆对象。


    对象使用:
      1、都可以被引用,x=obj
      2、都可以当做函数的参数传入
      3、都可以当做函数的返回值
      4、都可以当做容器类的元素(列表、元组、字典、集合,可以装多种值)


    元类

    产生类的类称之为元类,默认用class定义的类,他们的元类是type

    定义类的两种方式:

    方式一:class

    class Chinese(objext,metaclass = type):   # Chinese = type(...) metaclass元类
        country = "China"
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def talk(self):
            print("%s is talking" %self.name)
    

    方式二:type
    定义类的三要素:类名、类的基类们。类的名称空间
    类名(字符串):class_name = "Chinese"
    继承(元组形式):class_bases = (object,)
    类体(定义阶段类体代码立即执行)类的名称空间(字典形式):class_dic

    # 类的名称空间的产生
    class_body ='''
    country = "China"
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def talk(self):
        print("%s is talking" %self.name)
    '''
    class_dic = {}
    exec(class_body,globals(),class_dic)
    print(class_dic)
    
    #实例化
    Chinese = type(class_name,class_bases,class_dic) # 实例化元类,得到元类的对象(就是用class声明的类)

    自定义元类,控制类的行为

    class Foo:
        """注释"""
        pass
    print(Foo.__dict__)
    

    #__doc__ 存放注释信息

    class Mymeta(type):
        def __init__(self,class_name,class_bases,class_dic):
            if not class_name.istitle():   # 判断类名首字母有无大写(自定义)
                raise TypeError("类名首字母必须大写")
    
            if '__doc__' not in class_dic or not class_dic["__doc__"].strip():   # 判断有无注释
                raise TypeError("必须有注释且注释不能为空")
            
            super(Mymeta,self).__init__(class_name,class_bases,class_dic)
    
    
    class Chinese(object,metaclass = Mymeta):
        """自定义元类"""
        country = "China"
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def talk(self):
            print("%s is talking" %self.name)
    

    自定义元类,控制实例化的行为

    __call__

    # __call__方法 调用对象会触发__call__,将对象本身连同参数一起传入该方法中。

    __call__控制类的实例化行为

    __init__控制类的创建行为

    class Foo:
        def __call__(self, *args, **kwargs):
            print(self)
            print(args)
            print(kwargs)
    obj = Foo()
    obj(1,2,3,a=1,b=2,c=3)   # obj.__call__(obj,1,2,3,a=1,b=2,c=3)

    <__main__.Foo object at 0x000002C36C7F0358>
    (1, 2, 3)
    {'a': 1, 'b': 2, 'c': 3

    元类内部也应该有一个__call__方法,会在调用Foo时触发执行
    Foo(1,2,x=1) # Foo.__call__(Foo,1,2,x=1)

    class Mymeta(type):
        def __init__(self,class_name,class_bases,class_dic):
            if not class_name.istitle():   # 判断类名首字母有无大写(自定义)
                raise TypeError("类名首字母必须大写")
    
            if '__doc__' not in class_dic or not class_dic["__doc__"].strip():   # 判断有无注释
                raise TypeError("必须有注释且注释不能为空")
    
            super(Mymeta,self).__init__(class_name,class_bases,class_dic)
    
        def __call__(self, *args, **kwargs):
            print(self)     # self= Chinese
            print(args)     # args=('alex',)
            print(kwargs)   # kwargs={'age': 18}
    
    
    class Chinese(object,metaclass = Mymeta):
        """自定义元类"""
        country = "China"
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def talk(self):
            print("%s is talking" %self.name)
    
    obj = Chinese("alex",age=18)      # Chinese.__call__(Chinese,"alex",18)

    <class '__main__.Chinese'>
    ('alex',)
    {'age': 18}

    控制类的实例化行为

    class Mymeta(type):
        def __init__(self,class_name,class_bases,class_dic):
            if not class_name.istitle():   # 判断类名首字母有无大写(自定义)
                raise TypeError("类名首字母必须大写")
    
            if '__doc__' not in class_dic or not class_dic["__doc__"].strip():   # 判断有无注释
                raise TypeError("必须有注释且注释不能为空")
    
            super(Mymeta,self).__init__(class_name,class_bases,class_dic)
    
        def __call__(self, *args, **kwargs):   #obj = Chinese("alex",age=18)
            # print(self)     # self= Chinese
            # print(args)     # args=('alex',)
            # print(kwargs)   # kwargs={'age': 18}
            # 第一步:创造一个空对象
            obj = object.__new__(self)
            # 第二部:初始化obj
            self.__init__(obj,*args, **kwargs)
            # 第三部:返回obj
            return obj
    
    
    class Chinese(object,metaclass = Mymeta):
        """自定义元类"""
        country = "China"
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def talk(self):
            print("%s is talking" %self.name)
    
    obj = Chinese("alex",age=18)      # Chinese.__call__(Chinese,"alex",18)
    print(obj.__dict__)
    

      {'name': 'alex', 'age': 18}


    自定义元类控制类的实例化行为的应用

    单例模式 参数一样,不要再新生新的内存空间

    实现方式1:

    class MySQL:
        __instance = None
        def __init__(self):
            self.host = "127.0.0.1"
            self.port = 3306
    
        @classmethod
        def singleton(cls):
            if not cls.__instance:   #没有就创建
                obj = cls()
                cls.__instance = obj
            return cls.__instance
    
        def conn(self):
            pass
        def execute(self):
            pass
    
    obj1 = MySQL.singleton()
    obj2 = MySQL.singleton()
    
    print(obj1 is obj2)

    True

    实现方式2:通过元类实现

    class Mymeta(type):
        def __init__(self,class_name,class_bases,class_dic):    #控制类的创建行为
            if not class_name.istitle():   # 判断类名首字母有无大写(自定义)
                raise TypeError("类名首字母必须大写")
    
            if '__doc__' not in class_dic or not class_dic["__doc__"].strip():   # 判断有无注释
                raise TypeError("必须有注释且注释不能为空")
    
            super(Mymeta,self).__init__(class_name,class_bases,class_dic)
            self.__instance = None
    
        def __call__(self, *args, **kwargs):   #控制类的实例化行为
            # 第一步:创造一个空对象
            if not self.__instance:
                obj = object.__new__(self)
            # 第二部:初始化obj
            self.__init__(self)
            self.__instance = obj
            # 第三部:返回obj
            return self.__instance
    
    class Mysql(object,metaclass=Mymeta):
        """自定义元类控制类的实例化行为的应用"""
        __instance = None
        def __init__(self):
            self.host = "127.0.0.1"
            self.port = 3306
    
        @classmethod
        def singleton(cls):
            if not cls.__instance:   #没有就创建
                obj = cls()
                cls.__instance = obj
            return cls.__instance
    
        def conn(self):
            pass
        def execute(self):
            pass
    
    obj1 = Mysql.singleton()
    obj2 = Mysql.singleton()
    
    print(obj1 is obj2)
    

      True

  • 相关阅读:
    python使用消息队列RabbitMq(入门)
    python Condition类(锁)
    python锁
    python多线程的几种情形分析-三种情况
    git基本使用
    python学习笔记之数据类型、字符编码、文件处理
    NOIP2018提高组模拟题(五)
    10.28模拟赛
    差分+树状数组【p4868】Preprefix sum
    线段树【p2706】贪婪大陆
  • 原文地址:https://www.cnblogs.com/fantsaymwq/p/9911102.html
Copyright © 2011-2022 走看看