• python 之 面向对象(元类、__call__、单例模式)


    7.13 元类

    元类:类的类就是元类,我们用class定义的类来产生我们自己的对象的,内置元类type是用来专门产生class定义的类

    code="""
    global x     
    x=0
    y=2
    """                           #字符串内声明的名称是全局,其他为局部名称
    global_dic={'x':100000}
    local_dic={}                   # 运行字符串内代码
    exec(code,global_dic,local_dic) # 把全局名称空间的名称放入global_dic,把局部的放入local_dic
    print(global_dic)              #{'x': 0}
    print(local_dic)               #{'y': 2}

    7.131 用内置的元类type,来实例化得到我们的类

    class_name='Chinese'
    class_bases=(object,)   #基类
    class_body="""
    country="China"
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex
    def speak(self):
        print('%s speak Chinese' %self.name)
     """
    class_dic={}
    exec(class_body,{},class_dic)
    ​
    # 类的三大要素
    print(class_name,class_bases,class_dic) # Chinese (<class 'object'>,) {'country':'China', '__init__': <function __init__ at ...>, 'speak': <function speak at....>}
    ​
    Chinese=type(class_name,class_bases,class_dic)  #实例化一个类
    print(Chinese)                               #<class '__main__.Chinese'>
    ​
    p=Chinese('egon',18,'male')  #实例化对象p
    print(p.name,p.age,p.sex)    # egon 18 male  #说明和class定义的类功能相同

    7.132 __call__方法

    在调用对象时自动触发__call__的执行

    class Foo:
         def __init__(self):
             passdef __call__(self, *args, **kwargs):# 调用对象,则会自动触发对象下的绑定方法__call__的执行,
             print('__call__',*args, **kwargs)# 然后将对象本身当作第一个参数传给self,将调用对象时括号内的值传给*args与**kwargs
    obj=Foo()
    obj(1,2,3,a=1,b=2,c=3) #对象调用

    7.133 自定义元类来控制类的创建行为

    class Mymeta(type):   
         def __init__(self,class_name,class_bases,class_dic): #self=Foo
             print(class_name)
             print(class_bases)
             print(class_dic)
             if not class_name.istitle():                       #控制类名首字母必须大写
                 raise TypeError('类名的首字母必须大写傻叉')
    ​
             if not class_dic.get('__doc__'):                   # 控制文档注释必须存在
                 raise TypeError('类中必须写好文档注释,大傻叉')
    ​
             super(Mymeta,self).__init__(class_name,class_bases,class_dic)  #重用父类功能
    #Foo=Mymeta('Foo',(object,),class_dic)
    class Foo(object,metaclass=Mymeta): # metaclass=Mymeta创建自定义元类
         """
         文档注释
         """

    7.134 自定义元类来控制类的调用

    控制类Foo的调用过程,即控制实例化Foo的过程

    class Mymeta(type):   
         def __init__(self,class_name,class_bases,class_dic): #self=Foo
             print(class_name)
             print(class_bases)
             print(class_dic)
            
         def __call__(self, *args, **kwargs): #self=Foo,args=(1111,) kwargs={}
             #1 造一个空对象obj
             obj=object.__new__(self)
    ​
             #2、调用Foo.__init__,将obj连同调用Foo括号内的参数一同传给__init__
             self.__init__(obj,*args,**kwargs)
             return obj
    #Foo=Mymeta('Foo',(object,),class_dic)
    class Foo(object,metaclass=Mymeta): 
         x=1
         def __init__(self,y):
             self.y=y
    ​
         def f1(self):
             print('from f1')
    obj=Foo(1111)           #Foo.__call__()
    print(obj)              #<__main__.Foo object at 0x000002019EE1BB70>
    print(obj.y)            # 1111
    print(obj.f1)           #<bound method Foo.f1 of <__main__.Foo object at 0x000002019EE1BB70>>
    print(obj.x)            # 1

    7.14 单例模式

    对于对象通过相同的配置文件进行实例化,可以使几个对象使用同一个内存地址,节省内存

    import settings
    class MySQL:
        __instance=None
        def __init__(self,ip,port):
            self.ip=ip
            self.port=port
    ​
        @classmethod
        def singleton(cls):
            if not cls.__instance:
                obj=cls(settings.IP, settings.PORT)
                cls.__instance=obj
            return cls.__instance
    ​
    obj1=MySQL('1.1.1.2',3306)
    obj2=MySQL('1.1.1.3',3307)
    obj3=MySQL('1.1.1.4',3308)
    ​
    obj4=MySQL.singleton()          # obj4=MySQL(settings.IP,settings.PORT)
    obj5=MySQL.singleton()
    obj6=MySQL.singleton()
    print(obj4.ip,obj4.port)        # 1.1.1.1 3306
    print(obj4 is obj5 is obj6)     # True
  • 相关阅读:
    (七) rest_framework GenericAPIView/GenericViewSet/ ModelViewSet 解析
    (六) rest_framework 普通分页与加密分页
    (五) rest_framework 序列化与解析器源码实现
    (四) rest_framework 版本控制源码
    【使用 PySpark 分析 CSV 文件】
    安装 HBase1.3.6 on Windows 10 64 bit
    Spark Job 性能调优 (二)
    Spark RDD 分区到底怎么用?
    安装 Spyder python 开发环境 用于 Spark 数据分析 -word count
    安装 Spark on Windows 使用 PySpark
  • 原文地址:https://www.cnblogs.com/mylu/p/11160439.html
Copyright © 2020-2023  润新知