zoukankan      html  css  js  c++  java
  • 反射,魔法方法,单例模式

    1. 绑定方法

    • 绑定方法就是在书写这个方法时,会有一个默认参数(作为第一个参数),绑定给类,这个参数就是 cls ,绑定给对象这个参数就是self

    • 绑定方法的特殊之处:

      谁来调用自己的绑定方法,就把谁当作第一个参数传给该方法。

      但当类调用对象的绑定方法时,self 就是一个普通的形参,需要传给他一个实参,对象调用类的绑定方法同理

    • 对象的绑定方法的特殊之处:

      由对象来调用,会将对象当作第一个参数传给该方法

    • 类的绑定方法的特殊之处:

      由类来调用,会将类当作第一个参数传给该方法

    2. 类内部方法的装饰器

    • 之前还讲过的有 property ,作用是让这个方法不用加括号就可以调用。让它看起来就像是一个数据属性。

    1. classmethod

    • classmethod 就是一个装饰器。装饰类内部的方法,使该方法绑定来使用。

    2. staticmethod

    • staticmethod 也是一个装饰器。装饰类内部的方法。使该方法既不绑定给类,也不绑定给对象,此时就是作为普通函数。

    3. uuid模块

    是一个加密模块,uuid中的uuid4方法通过时间戳生成一个世界上唯一36位的字符串对象(注意是对象,可以强制类型转换成字符串)。hashlib产生的是32位的加密字符字符串。random.random() 产生的是一个有16位小数的0~1之间随机小数。
    
    • 应用实例:

      import hashlib
      import uuid
      
      class Teacher:
          def __init__(self, user, pwd):
              self.user = user
              self.pwd = pwd
      
          # 主页
          def index(self):
              if self.user == 'tank' and self.pwd == '123':
                  print('验证通过,显示主页...')
      
          @classmethod
          def login_auth_from_settings(cls):
              obj = cls('tank', '123')
              return obj  # Teacher() ---> return = obj
      
          @staticmethod
          def create_id():
              # 生成一个唯一的id字符串
              uuid_obj = uuid.uuid4()
              md5 = hashlib.md5()
              md5.update(str(uuid_obj).encode('utf-8'))
              return md5.hexdigest()
      
      obj = Teacher.login_auth_from_settings()
      obj.index()  # 验证通过,显示主页...
      
      tea1 = Teacher('tank', '123')
      tea1.index() # 验证通过,显示主页...
      
      print(type(uuid.uuid4()))
      
      print(Teacher.create_id()) # 类调用这个普通函数
      tea1 = Teacher('tank', '123')
      print(tea1.create_id())  # 对象调用这个普通函数
      
      

    3.isinstance与issubclass函数

    • 他们都是python内置的函数。

    • isinstance(参数1,参数2)

      判断参数1是否是参数2的一个实例

    • issubclass

      判断参数1是否是参数2的子类

    4. 反射

    • 反射就是通过字符串来操作类或者对象的属性
    • 反射本质就是在使用内置函数,其中反射有以下四个内置函数:
    1. hasattr:判断一个方法是否存在与这个类中
    使用方法:
    hasattr(对象或类名,属性名)
    
    2. getattr:根据字符串去获取obj对象里的对应的方法的内存地址,加"()"括号即可执行
    例如:
    使用方法:
     foo = getattr(对象或类名,属性名1,默认值) 默认值可加可不加,没有默认值默认是None。和字典内置方法的get同样的用法。
     若该属性为方法属性时:  
     foo()  就相当于——》 对象.属性名1()
    
    3. setattr:通过setattr将外部的一个函数绑定到实例中
    使用方法:
    setattr(对象名或者类名,属性名,属性值)
    遵循:有就修改,没有就添加
    
    4. delattr:删除一个实例或者类中的方法
    使用方法:
    delattr(对象名或者类名,属性名)
    

    5. 魔法方法

    • 凡是在类内部定义,以“__开头__结尾”的方法都称之为魔法方法,又称“类的内置方法”。魔法方法会在某些条件成立时触发。
      
    1. 定义类时最先触发:
    
     __new__: 会在__init__执行前触发,如果当前类的__new__ 没有return 一个空对象,则不会触发__init__。
    
    2. 对类的操作时触发:*****************************
    
        __init__: 在执行程序时遇到 调用类 时触发。
            
    3. 对对象的操作时触发:这种触发相当于是让触发条件这个代码变得没有意义,且变成对触发方法的调用******************************* 
    
        __str__: 会在执行程序时,遇到 打印对象 时触发。必须要有一个返回值, 该返回值必须是字符串类型
        __del__: 对象被销毁前(有删除对象和程序执行结束时触发)
            	 删除对象时,执行该方法。
                 程序执行要结束前执行该方法,该方法会在最后执行。
                    
        __delattr__ : 会在执行程序时遇到删除对象属性(即 del 对象.属性 【无论这个属性是对象自己的还是类的】 )时触发
        而且 del 对象.属性  并没有删除该属性 ,他只是作为一种触发条件,其本身的意义不存在。
        del  类名.属性  会删除类的该属性 ,删除类的属性不会触发 __delattr__
        
        __getattr__: 会在执行程序时遇到 对象.属性 或者 getattr 方法时,并且 “属性没有” 的情况下才会触发,对象.属性 或者 getattr 他只是作为一种触发条件,其本身的意义不存在。所他们的返回值变成了__getattr__ 这个函数的返回值。
        __getattribute__ : 会在执行程序时遇到 对象.属性 或者 getattr 方法 时,无论 “属性有或者没有” 的情况下都会触发。对象.属性 或者 getattr 他只是作为一种触发条件,其本身的意义不存在,相当于调用__getattr__。所以他们的返回值变成了 __getattribute__ 这个函数的返回值。
        当 __getattr__ 和 __getattribute__ 同时存在,只会触发__getattribute__ 。
    
        __setattr__: 会在执行程序时遇到 “对象.属性 = 属性值” 时触发。此时,这个赋值操作是失效的,就是说没有对这个属性赋值,他只是作为一种触发条件,其本身的意义不存在。要想对一个属性赋值,可以使用`对象.__dict__[属性名] = 属性值`方式新增属性或者修改属性。
    
        __call__: 会在对象被调用时触发。只有类的内部有这个方法时,对象才能加括号进行对象调用,否则对象加括号会报错。
    

    6. 单例模式

    1. 什么是单例模式

    • 单例模式:基于某种方法实例化多次得到实例是同一个

    2. 为什么用单例模式

    • 当实例化多次得到的对象中存放的属性都一样的情况,应该将多个对象指向同一个内存,即使用同一个对象,但通过传入不同的参数,让这个对象的属性值不同。
      例如在一个程序运行时多个用户的注册,多个用户登陆等,都可以使用 。
    • 使用单例模式可以减少内存占用
    • 单例模式下,在程序的运行中,无论实例化多少个对象,这些对象用的都是第一次实例化产生的对象的内存地址。

    3. 三种单例方式:

    • 以下三种单例模式 , 推荐使用第二种(即 __new__的单例模式)
    • 三种单例模式的区别:
      第一种和第三种都是通过只调用一次类(即只进行一次类的实例化)的方式实现单例模式,第二种通过在类的定义时只产生一次空对象的方式实现单例模式,也就是说第二种无论调用多少次这个类都没有任何影响。

    (1)类内部定义 类的绑定方法

    
    IP = '1.1.1.1'
    PORT = 3306
      
    class Mysql:
        __instacne = None
    
        def __init__(self, ip, port):
            self.ip = ip
            self.port = port
    
        @classmethod
        def from_conf(cls):
            if cls.__instacne is None:
                cls.__instacne = cls(IP, PORT)  # 只能从此处传参
            return cls.__instacne
    
    
    obj1 = Mysql.from_conf()
    obj2 = Mysql.from_conf()
    obj3 = Mysql.from_conf()
    
    print(obj1 is obj2 is obj3)  # True
    

    (2)类内部通过__new__方法控制只创建一次空对象

    • 这种方法使得产生的对象都是第一次实例化的对象,但每次的参数都是最后一次实例化对象时传入的参数。
    
      IP = '1.1.1.1'
      PORT = 3306
        
      class Mysql:
        
        __instance = None
          
        def __new__(cls, *args, **kwargs):   
            if not cls.__instance:
                cls.__instance = object.__new__(cls)
            return cls.__instance
      
          def __init__(self, ip, port):
              self.ip = ip
              self.port = port
            
     # 除了最后一个对象的参数有意义,之前的参数都没有意义,所有对象都是第一个对象,但是属性都是使用最后一个实例化对象时传入的参数。
    
    obj1 = Mysql(IP,PORT) 
    obj2= Mysql(IP,PORT)
    obj3 = Mysql(55,66)
    
    print(obj1 is obj2 is obj3) # True
    
    
    

    (3)装饰器式的单例

    
    IP = '1.1.1.1'
    PORT = 3306
    
    
    def singleton(cls):
        cls.__instance = cls(IP, PORT)  # 只能在这里传参
    
        def wrapper(*args, **kwargs):
            if len(args) == 0 and len(kwargs) == 0:
                return cls.__instance
            return cls(*args, **kwargs)
    
        return wrapper
    
    
    @singleton  # Mysql = singleton(Mysql) # Mysql = wrapper
    class Mysql:
        def __init__(self, ip, port):
            self.ip = ip
            self.port = port
    
    
    obj1 = Mysql()  # wrapper()  # 这里和后面的都不能传参,如果传参,装饰器就什么事也没做,相当于没有装饰器。
    obj2 = Mysql()  # wrapper()
    obj3 = Mysql()  # wrapper()
    
    print(obj1 is obj2 is obj3) # True
    
  • 相关阅读:
    使用Jmeter对SHA1加密接口进行性能测试
    Introduction of JSON Processing and binding in JavaEE
    RE validation in Java EE(java.util.regex.Pattern)
    Analysis of Hello2 source code
    Spring AOP Capability and Goal
    Mysql :Datatype
    MYSQL Backup & Recovery
    JavaEE Design Patter(2)
    Analysis JSON / XML、 Processing Model 、Extend to JAVA Design Model
    Session & Cookie
  • 原文地址:https://www.cnblogs.com/Mcoming/p/11663354.html
Copyright © 2011-2022 走看看