day22总结

类的绑定方法

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

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

      扫描二维码关注公众号,回复: 7458718 查看本文章
      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__的返回值
    '''
  • __setattr__ : 在 对象.属性 = 属性值 时触发

    class Foo:
        def __setattr__(self, key, value):
            print(f'在 `对象.属性 = 属性值` 时触发,属性名为:{key},属性值为{value}')
    
    
    obj = Foo()
    obj.x = 10
    
    print('*' * 50)
    
    

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


对象.属性 = 属性值 时触发,属性名为:x,属性值为10


10
'''

  

- ```python
  class Foo:
      # 执行该方法时,外部 "对象.属性 = 属性值" 无效
      def __setattr__(self, key, value):
          print(f'在 `对象.属性 = 属性值` 时触发,属性名为:{key},属性值为{value}')
  
      def __getattr__(self, item):
          print('__getattr__测试', f',没有的属性为{item}')
  
  
  obj = Foo()
  print(obj.x, '\n', '*' * 30)
  obj.x = 10
  print(obj.__dict__, '\n', '*' * 30)
  print(obj.x, '\n', '*' * 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
    
        # 单例方式二:
        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)

猜你喜欢

转载自www.cnblogs.com/-406454833/p/11668482.html