• 类的绑定方法, 静态方法, 魔法方法, 反射, 单例模式


    类的绑定方法

    classmethod

    • 是一个装饰器,可以装饰给类内部的方法,使该方法绑定给类来使用

    • 由类来调用类中定义的函数称之为类的绑定方法,该函数会绑定给类使用,并且会将类当做该绑定方法的第一个参数自动传入

      class People:
          def __init__(self,name,age):
              self.name = name
              self.age = age
      
          @classmethod    #先使用装饰器默认添加函数参数 "cls"
          def prt_info(cls):
              print(f'''姓名: {cls('蔡启龙',25).name}
      年龄: {cls('蔡启龙',25).age}''')
      
      People.prt_info()
      print('*'*50)
      
      people = People('tank',30)
      people.prt_info()   #类的绑定方法也可以由对象调用,默认将该对象的类当做第一个参数传入绑定方法
      
      '''
      姓名: 蔡启龙
      年龄: 25
      **************************************************
      姓名: 蔡启龙
      年龄: 25
      '''
      
    import user_info_settings
    
    class Teacher:
        def __init__(self,username,pwd):
            self.username = username
            self.pwd = pwd
    
        #主页
        def index(self):
            if self.username == '蔡启龙' and self.pwd == '123':
                print('验证通过,显示主页')
    
        # 用户保存登录信息,提供自动登录接口
        @classmethod
        def login_auth(cls):
            obj = cls(user_info_settings.username,user_info_settings.pwd)
            obj.index()
    
    teacher = Teacher('蔡启龙','123')
    teacher.index()
    print('*'*16)
    
    Teacher.login_auth()    #调用自动登录接口
    
    '''
    验证通过,显示主页
    ****************
    验证通过,显示主页
    '''
    

    非绑定方法

    staticmethod

    • 是一个装饰器,可以装饰给类内部的方方法,使该方法既不绑定给类,也不绑定给对象

      import uuid  # 一个加密模块,其中的uuid4()方法可以通过时间戳生成一个世界上唯一的字符串
      import hashlib
      
      class Teacher:
          @staticmethod
          def creat_id():
              uuid_obj = uuid.uuid4()  # 返回值是一个对象
              m = hashlib.md5()
              m.update((str(uuid_obj).encode('utf-8')))
              print(m.hexdigest())
      
      Teacher.creat_id()	# 类调用非绑定方法
      teacher = Teacher()
      teacher.creat_id()	# 对象调用非绑定方法
      

    isinstance和issubclass

    判断一个对象是否是一个类的实例---isinstance

    • isinstance('参数1','参数2')

      • python内置的函数,可以传入两个参数,用于判断参数1是否是参数2的一个实例

        class Foo:
            pass
        
        
        class Goo:
            pass
        
        
        foo = Foo()
        print(foo.__class__)  # "__class__" 是对象的属性,获取对象所属的类
        print(isinstance(foo, Foo))	# True
        print(isinstance(foo, Goo))	# False
        

    判断一个类是否是另一个类的子类---issubclass

    • python内置函数,可以传入两个参数,用于判断参数1是否是参数2的子类

      class Foo:
          pass
      
      
      class Goo(Foo):
          pass
      
      
      class Hoo:
          pass
      
      
      print(issubclass(Goo, Foo))  # True
      print(issubclass(Hoo, Foo))  # False
      

    反射

    什么是反射?

    • 通过 "字符串" 对 对象或类的属性进行操作

    反射的四种方法

    • hasattr---查

      • 通过字符串,判断该字符串是否是对象或类的属性

        class People:
            country = 'China'
        
            def __init__(self, name):
                self.name = name
        
        
        people = People('蔡启龙')
        
        # 普通方式
        print('name' in people.__dict__)  # True
        print('country' in People.__dict__)  # True
        print('country2' in People.__dict__)  # False
        
        # hasattr
        print(hasattr(people, 'name'))  # True
        
    • getattr

      • 通过字符串,获取对象或类的属性

        class People:
            country = 'China'
        
            def __init__(self, name):
                self.name = name
        
        
        people = People('蔡启龙')
        
        # 普通方式
        print(people.__dict__.get('name', 'tank'))
        print(people.__dict__.get('score', 99))
        
        # getattr
        print(getattr(people, 'country', 'Japan'))
        print(getattr(People, 'country2', 'Japan'))
        
        '''
        蔡启龙
        99
        China
        Japan
        '''
        
    • setattr---改

      • 通过字符串,修改对象或类的属性

        class People:
            country = 'China'
        
            def __init__(self, name):
                self.name = name
        
        
        people = People('蔡启龙')
        
        # 普通方式
        people.score = '100'
        print(getattr(people, 'score', 99))
        
        # setattr
        setattr(people, 'country', 'America')
        print(getattr(People, 'country'))
        print(getattr(people, 'country'))
        
        '''
        100
        China
        America
        '''
        
    • delattr---删

      • 通过字符串,删除对象或类的属性

        class People:
            country = 'China'
        
            def __init__(self, name):
                self.name = name
        
        
        people = People('蔡启龙')
        
        # 普通方式
        del people.name
        print(hasattr(people, 'name'))  # False
        
        # delattr
        delattr(People, 'country')
        print(hasattr(People, 'country'))  # False
        
      • 反射小练习

        class Movie:
            def input(self):
                while True:
                    cmd = input('请输入执行的方法名:').strip()
        
                    # 判断用户指令是否存在
                    if hasattr(self, cmd):
                        method = getattr(self, cmd)
                        method()
                    else:
                        print('命令错误,请重新输入')
        
            def upload(self):
                print('电影开始上传...')
        
            def download(self):
                print('电影开始下载...')
        
        
        movie_obj = Movie()
        movie_obj.input()
        

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

    什么是类的魔法方法?

    • 在类的内部定义,以 __开头__结尾 的方法称为类的魔法方法,又称类的内置方法
    • 类的魔法方法会在默写条件成立时立即触发(调用)

    常用的类的魔法方法

    • __init__ : 在调用类时触发,用来给空对象初始化属性

    • __str__ : 打印对象时触发

      class Foo:
          # 该方法必须要有一个字符串数据类型的返回值,否则报错:TypeError: __str__ returned non-string (type NoneType)
          def __str__(self):
              print('打印对象时触发')
              return '__str__测试'  # 不使用该魔法方法打印对象时输出的结果是对象地址
      
      
      obj = Foo()
      print(obj)
      
      '''
      打印类象时触发
      __str__测试
      '''
      
      class MyList:
      
          def __init__(self, lt):
              self.lt = lt
      
          def __str__(self):
              return str(self.lt)
      
      
      lt = MyList([1, 2, 3])
      print(lt)  # [1, 2, 3]
      
    • __del__ : 在程序执行结束,对象被销毁前执行该方法

      class Foo:
          def __del__(self):
              print('对象被销毁前执行该方法')
      
      
      obj = Foo()
      print('程序执行完毕,准备销毁对象')
      
      '''
      程序执行完毕,准备销毁对象
      对象被销毁前执行该方法
      '''
      
    • __getattr__ : 在 对象.属性 ,属性没有时触发

      class Foo:
          # 默认返回None,若想打印属性的结果,必须return一个值
          def __getattr__(self, item):
              print('__getattr__测试', f',没有的属性为{item}')
              return '__getattr__的返回值'
      
      
      obj = Foo()
      print(obj.x)
      
      '''
      __getattr__测试 ,没有的属性为x
      __getattr__的返回值
      '''
      
    • __getattribute__ : 在 对象.属性 , 无论属性有没有, 都会触发

    • __setattr__ : 在 对象.属性 = 属性值 时触发

      class Foo:
          def __setattr__(self, key, value):
              print(f'在 `对象.属性 = 属性值` 时触发,属性名为:{key},属性值为{value}')
      
      
      obj = Foo()
      obj.x = 10
      
      print('*' * 50)
      
      '''
      在 `对象.属性 = 属性值` 时触发,属性名为:x,属性值为10
      **************************************************
      '''
      
    class Foo:
        def __setattr__(self, key, value):
            print(f'在 `对象.属性 = 属性值` 时触发,属性名为:{key},属性值为{value}')
            self.__dict__[key] = value
    
    
    obj = Foo()
    obj.x = 10
    print('*' * 50)
    
    print(obj.x)
    
    '''
    在 `对象.属性 = 属性值` 时触发,属性名为:x,属性值为10
    **************************************************
    10
    '''
    
    class Foo:
        # 执行该方法时,外部 "对象.属性 = 属性值" 无效
        def __setattr__(self, key, value):
            print(f'在 `对象.属性 = 属性值` 时触发,属性名为:{key},属性值为{value}')
    
        def __getattr__(self, item):
            print('__getattr__测试', f',没有的属性为{item}')
    
    
    obj = Foo()
    print(obj.x, '
    ', '*' * 30)
    obj.x = 10
    print(obj.__dict__, '
    ', '*' * 30)
    print(obj.x, '
    ', '*' * 30)
    
    '''
    __getattr__测试 ,没有的属性为x
    None 
     ******************************
    在 `对象.属性 = 属性值` 时触发,属性名为:x,属性值为10
    {} 
     ******************************
    __getattr__测试 ,没有的属性为x
    None 
     ******************************
    '''
    
    • __call__ : 在对象被调用时触发

      class Foo:
          def __call__(self, *args, **kwargs):
              print(f'{self},调用对象时触发')
      
      
      obj = Foo()
      obj()
      
      # <__main__.Foo object at 0x000001A275CDD278>,调用对象时触发
      
    • __new__ : 在 __init__ 执行前触发,用来生成一个空对象

      class Foo:
          # 真正用来生成一个空对象,需要通过return才能将空对象返回出去.
          def __new__(cls, *args, **kwargs):
              print(cls)
              return object.__new__(cls)
      
          # 给空对象初始化属性,若当前类的__new__方法没有return一个空对象,则不会触发.
          def __init__(self):
              print('初始化空对象时调用')
      
      
      obj = Foo()
      
      '''
      <class '__main__.Foo'>
      初始化空对象时调用
      '''
      

    类的魔法方法 __del__ 的应用

    • class MyOpen:
          def __init__(self, filename, mode='r', encoding='utf-8'):
              self.filename = filename
              self.mode = mode
              self.encoding = encoding
      
          # 句柄:一种特殊的只能指针引用对象或内存块时候使用
          def file_open(self):
              self.f = open(self.filename, self.mode, encoding=self.encoding)  # 产生句柄并当做属性添加到实例化出的对象中
      
          def file_read(self):
              res = self.f.read()
              print(f'''当前文件名称: {self.filename}
      当前文件数据: {res}''')
      
          def __del__(self):
              self.f.close()
              print('文件关闭成功')
      
      
      openmyfile = MyOpen('蔡启龙雨后的小故事')
      openmyfile.file_open()
      openmyfile.file_read()
      
      print('程序执行结束,准备销毁对象')
      

    单例模式

    什么是单例模式

    • 实例化多个对象会产生不同的内存地址
    • 单例模式可以使每次实例化产生的对象都使用同一个地址
    • 例如打开文件的操作

    单例模式的目的

    • 减少内存占用

    如何实现

    • '''
      从配置文件中获取相同的文件名的数据
      '''
      
      
      class MyOpen:
          __instance = None  # 访问限制机制
      
          # 单例方式一:    # 类的绑定方法
          @classmethod
          def singleton(cls, filename):
              if not cls.__instance:
                  obj = cls(filename)
                  cls.__instance = obj
              return cls.__instance
      
          # 单例方式二:    # 魔法方法__new__
          def __new__(cls, *args, **kwargs):
              if not cls.__instance:
                  cls.__instance = object.__new__(cls)
              return cls.__instance
      
          def __init__(self, filename, mode='r', encoding='utf-8'):
              self.filename = filename
              self.mode = mode
              self.encoding = encoding
      
          def open(self):
              self.f = open(self.filename, self.mode, encoding=self.encoding)
      
          def read(self):
              res = self.f.read()
              print(res)
      
          def close(self):
              self.f.close()
      
      
      # obj1 = MyOpen.singleton('蔡启龙雨后的小故事.txt')
      # obj2 = MyOpen.singleton('蔡启龙雨后的小故事.txt')
      # print(obj1)
      # print(obj2)
      
      obj3 = MyOpen('蔡启龙雨后的小故事.txt')
      obj4 = MyOpen('蔡启龙雨后的小故事.txt')
      print(obj3)
      print(obj4)
      
  • 相关阅读:
    棋盘问题 POJ
    Fire! UVA
    走迷宫(bfs, 最短路)
    ASP-Command-SQL格式
    ASP连接数据库SQLServer
    Bootstrap学习-导航条-分页导航
    Bootstrap导航栏头部错位问题
    SQLServer判断一个IP是否在一个IP段里
    MySQL合并多行
    CSS图片居中,多余隐藏
  • 原文地址:https://www.cnblogs.com/-406454833/p/11668482.html
Copyright © 2020-2023  润新知