zoukankan      html  css  js  c++  java
  • 类的内置方法(魔法方法) 单例模型

    类的内置方法(魔法方法)

    凡是在类内部定义的,以——开头——结尾的方法,都是类的内置方法,也称之为魔法方法。

    会在某种条件下满足自动触发。

    ——init——触发前,调用该类时,内部会通过——new——产生一个新的对象。

    ——init——:在调用类时自动触发,通过产生的对象自动调用——init——()(**——new——产生的新的对象 ,触发了——init——调用)

    1——init—— 和——new——的用法

    class Demo(object):##这个里面的object就是一个新式类 父类
    
        # 在调用类时触发
        def __init__(self):
            print('在调用类时触发... ')
     # Demo()  调用类
     #####在调用类时触发... 
           # 条件__new__:在__init__触发前,自动触发。
          def __new__(cls, *args, **kwargs):
                print('此处是__new__方法的执行')
            # python内部通过object调用内部的__new__实现产生一个空的对象,然后再去执行__init__
            return object.__new__(cls, *args, **kwargs)
    
    # Demo()
    ###此处是__new__方法的执行
    ###在调用类时触发... 
    

    2.——getattr——

    class Demo:
    
        #在“对象.属性”获取属性的时候,如果没有'属性'时触发
        def __getattr__(self, item):##这个是属性名
            print('此处是__getattr__方法的执行')
            print(item)
            return 123
    
    obj = Demo()
    print(obj.x)
    >>>>>>>>>>>>>>>>>>
    此处是__getattr__方法的执行
    x
    123
    如果obj.x = 2
    print(obj.x)
    最后的结果就是
    2###return的结果会被改为2   但是属性print值就不会触发 
    

    3.——getattribute——

    class Demo:
        #__getattribute__:在“对象.属性”获取属性的时,无论属性有或者没有
        #都会触发
        y = 12
        def __getattribute__(self,item):
            print(item,'----要打印的东西') #item指的是变量名
            
            #如下面的例子,此处不能通过对象.属性 ,否则会产生递归,程序崩溃,
            # print(self.__dict__)
            # return self.__dict__[item]
            # return self.__dict__[item]
    
    
    obj = Demo()
    # obj.x
    obj.y = 2
    print(obj.y,'---打印出值')  ###打印结果都是None
    >>>>>>>>>>>>>>>
    y ----要打印的东西
    None ---打印出值
    

    注意:只要——getattr 和——getattribute 同时存在的数据,只会触发——getattribute——

    4.——setattr——

    class Demo:
        #只有当“对象.属性 = 属性值”,添加或者修改属性时触发
        def __setattr__(self, key, value):
            print('此处是__setattr__方法的执行')
            print(key,value)
            #下面的情况出现了递归
            # self.key = value
            print(self.__dict__)###打印的是一个空{}
            self.__dict__[key] = value###这个是一个字典{‘x’:30} 把新加的值30放进去obj的名词空间里面,才可以打印的出来
    
    obj = Demo()
    obj.x = 2
    obj.x = 30
    print(obj.__dict__)#打印的是空字典,原来设置属性的时候,会自动触发父类中的__setattr__
    #内部为对象添加x属性,值为20,如果把__setattr__删除,obj对象中的属性x 才会存在
    >>>>>>>>>>>>>>>>
    此处是__setattr__方法的执行
    x 2
    {}
    此处是__setattr__方法的执行
    x 30
    {'x': 2}
    {'x': 30}
    
    

    5.——call——

    class Demo:
        #条件:在调用对象 “对象+()”时触发
        def __call__(self, *args, **kwargs):
            print("此处是__call__方法的执行")
            return [1,2,3,4]
    
    obj = Demo()
    res = obj()
    print(res)
    >>>>>>>>>>>>
    此处是__call__方法的执行
    [1, 2, 3, 4]
    
    

    6.——str——

    class Demo:
        #条件:在打印对象时触发
        #该方法必须有一个字符串的返回值
        def __str__(self):
            print('此处是__str__的方法执行')
            return '111'
    
    obj = Demo()
    print(obj)
    >>>>>>>>>>>>
    此处是__str__的方法执行
    111
    

    7.——getitem——

    class Demo:
        #在对象通过“对象[key]”获取属性时触发
        def __getitem__(self, item):
            print('此处是__getitem__的方法执行')
            print(item)
            return self.__dict__[item]###这个是一个字典
    obj = Demo()
    obj.x = 2
    print(obj['x'])
    >>>>>>>>>>>>>>>>>
    此处是__getitem__的方法执行
    x
    2
    

    单例模型

    定义:指的是在确定“类中的属性和方法”不变时,需要反复调用类,产生不同的对象,会产生不同的内存地址,造成资源的浪费。

    让所有的类实例化,指向同一个内存地址,称之为单例模式------->无论产生多少个内存对象,都会指向一个实例。

    class Foo:
        def __init__(self,x,y):
            self.x = x
            self.y = y
    foo_obj1 = Foo(10,20)
    print(foo_obj1.__dict__)
    print(foo_obj1)
    
    foo_obj2 = Foo(20,30)
    print(foo_obj2.__dict__)
    print(foo_obj2)
    ##foo_obj1 和foo_obj2 的内存空间的地址不一样
    >>>>>>>>>>>>>>>
    {'x': 10, 'y': 20}
    <__main__.Foo object at 0x000002B4F12BF2E8>
    {'x': 20, 'y': 30}
    <__main__.Foo object at 0x000002B4F12BF400>
    

    单例模式

    1.通过classmethod

    2.通过装饰器

    3.通过——new——实现

    4.通过元类实现

    5.通过模块实现

    
     方式一: classmethod
    class Singleton1:
    
        __instance = None
    
         @classmethod
        def singleton(cls):
    
             if not cls.__instance:
                 cls.__instance = cls() #第一次产生一个obj时 走这个if判断,会把这个__instance附一个值是obj 下次 类再产生对象时 ,因为__instance已经有值了 这个if就不会走了 直接把这之前的obj返回出去,这样就保证了一致性。
    
             return cls.__instance
    obj1 = Singleton.singleton()
    obj2 = Singleton.singleton()
    print(obj1)
    print(obj2)
    
    #这个是复杂的一点的方法
    setting中的值
    HOST = '180.101.49.12'
    PORT = 443
    
    import setting
    class MySQL:
        #一个默认的值,用于判断对象是否存在,对象不存在证明值是None
        #—__instance 是类的属性,可以用类来调用
        __instance = None
        def __init__(self,host,port):
            self.host = host
            self.port = port
    
        @classmethod
        def singleton(cls,host,port):##单例的类方法
            #判断__instance中若没有值,证明没有对象
            if not cls.__instance:
                #产生一个对象并返回
                obj = cls(host,port)
                #
                cls.__instance = obj
            #若__instance 中有值,证明对象存在,则直接返回该对象
            return cls.__instance
    
        def start_mysql(self):
            print('启动mysql')
    
        def close(self):
            print('关闭mysql')
    
    obj1 = MySQL.singleton(setting.HOST,setting.PORT)
    print(obj1)
    
    obj2 = MySQL.singleton(setting.HOST,setting.PORT)
    print(obj2)
    >>>>>>>>>>>>>>>>>>>>
    <__main__.MySQL object at 0x0000019B5F8FFF60>######现在这个内存地址就是一样了
    <__main__.MySQL object at 0x0000019B5F8FFF60>
    

    通过模块实现

    #模块 demo
    class Singleton:
        pass
    
    obj = Singleton()
    
    #下面的是另外一个py模块的调用(在同一个py页里面)
    from demo import obj
    print(obj)
    
    from demo import obj
    print(obj)
    >>>>>>>>>>>>>>>>
    <demo.Singleton object at 0x000001E1463044E0>
    <demo.Singleton object at 0x000001E1463044E0>
    
    

    通过装饰器

    #用装饰器的方法
    def singleton(cls):
        __instance = {} ##这个字典是一个可变的类型,我每次往里面的值obj发生改变 这个的内存地址都不会变,所以是打印出来的内存地址都是一样的
    
        def inner(*args, **kwargs):
            if cls not in __instance:
                obj = cls (*args,**kwargs)
                __instance[cls] = obj
    
            return __instance[cls]
        return inner
    
    @singleton
    class Father:
        pass
    print(Father())
    print(Father())
    >>>>>>>>>>>>>
    <__main__.Father object at 0x0000019FDD15F518>
    <__main__.Father object at 0x0000019FDD15F518>
    

    通过__new__ d的方法

    class Singleton2:
        __instance  = None
    
        def __new__(cls,*args,**kwargs):###这个是重写了父类的--new-- 父类里面的还是存在的,只是这个用于 调用--new--的方法 会先从类中查找,因为类中重写了 ,有。
                cls.__instance = object.__new__(cls)
            return cls.__instance
    obj1 = Singleton2()
    print(obj1)
    obj2 = Singleton2()
    print(obj2)
    >>>>>>>>>>>>>>
    <__main__.Singleton2 object at 0x0000023C04EFF518>
    <__main__.Singleton2 object at 0x0000023C04EFF518>
    
  • 相关阅读:
    os 模块1
    除法
    python基础四(jsonossys andomstring模块、文件、函数)
    python基础三(集合、文件)
    linux下mysql安装
    linux下tomcat安装
    linux系统jdk安装
    python基础二(list,tuple元祖、dic字典,字符串)
    python基础一(安装、变量、循环、git)
    charles抓包
  • 原文地址:https://www.cnblogs.com/bs2019/p/11991678.html
Copyright © 2011-2022 走看看