• 面向对象进阶


    面向对象进阶

    Wisdom is knowing what to do next , virtue is doing it .

    classmethod 和 staticmethod

    classmethod

    装饰给类内部的方法,使该方法绑定给类使用。由类调用,将类作为第一个参数传入方法,不影响对象对该方法的调用。

    class People:
        def __init__(self,name,age):
            self.name = name
            self.age = age
            print(self)
    
        @classmethod
        def tell_info(cls):
            print(cls)#这里只是说明这个方法已经绑定给了类,所以其参数是类
            print('此处是类方法。。。')
    
    p = People('tank',18)
    p.tell_info()
    #<__main__.People object at 0x00000272647D8A20>
    # <class '__main__.People'>
    # 此处是类方法。。。
    
    

    staticmethod

    是一个装饰器,可以装饰给类内部的方法,使该方法不绑定给对象,也不绑定给类使其变成一个普通的函数,但是不改变其调用方式。(__class__对象的属性,获取当前对象的类)

    小练习

    1、定义MySQL类
    1.对象有id、host、port三个属性
      

      2.定义工具create_id,在实例化时为每个对象随机生成id,保证id唯一
      
      3.提供两种实例化方式,方式一:用户传入host和port 方式二:从配置文件中读取host和port进行实例化

    #下面代码仅给出了实例化的两种方式,和ID的产生
    import hashlib,uuid,settings#settings为配置文件(配置文件其实就是一个自定义的模块)
    class Teacher:
        def __init__(self,user,pwd):#通过对象的绑定方法产生一个对象(对象名 = 类(参数))
            self.user = user
            self.pwd = pwd
    
        def index(self):
            if self.user == 'tahk' and self.pwd == '123':
                print('验证通过,显示主页。。。')
    
        @classmethod
        def login_auth_from_settings(cls):#通过配置文件的方式产生一个对象(通过类的绑定方法产生一个对象)
            obj = cls(settings.USER,settings.PWD)
            return obj
    
        @staticmethod
        def create_id():
            uuid_obj = uuid.uuid4()
            md5 = hashlib.md5()
            md5.update(str(uuid_obj).encode('utf8'))
            return md5.hexdigest()
    
    obj = Teacher.login_auth_from_settings()#通过配置文件产生对象需要单独调用实例化方法
    obj.index()
    tea1 = Teacher('tank', '123')
    print(tea1.create_id())
    tea1.index()
    print(Teacher.create_id())
    

      

    isinstance 和 issubclass

    isinstance

    isinstance******(参数1,参数2)返回bool值判断参数1(对象)是否是参数二(类)的实例。

    issubclass

    issubclass*****判断参数一(子类)是否是参数二(父类)的子类反射*******指通过字符串对对象或类的属性进行操作。

    class Foo:
        pass
    
    class Goo(Foo):
        pass
    
    
    foo_obj = Foo()
    print(isinstance(foo_obj, Foo))
    print(isinstance(foo_obj, Goo))  # False
    print(issubclass(Goo, Foo))  # True
    

    反射

    反射指通过字符串对对象或类的属性进行操作。

    hasattr:通过判断该字符串是否是对象或类的属性。

    getattr:通过字符串获取对象或类的属性。

    setattr:通过字符串设置对象或类的属性,如果属性不存在会为对象添加属性。

    delattr:通过字符串删除对象或类的属性。

    class People:#创建一个类
        country = 'China'
    
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    p = People('tank',17,'male')
    #普通方式
    print('name' in p.__dict__)#判断name是否是对象的属性值
    #hasattr
    print(hasattr(p,'name'))
    print(hasattr(People,'country'))
    #获取属性值
    #普通方式
    print(p.__dict__.get('name'))
    #getattr
    print(getattr(p,'name','jason_sb'))#如果有值则返回属性值,如果没有则返回最右侧的这个值
    print(getattr(People,'country2','China'))
    #为对象或类添加属性
    #普通方式
    p.level = 10
    print(p.level)
    #setattr
    setattr(p,'sal','3.0')
    print(hasattr(p,'sal'))
    #删除对象的属性
    #普通方式
    del p.level
    print(hasattr(p,'level'))
    #delattr
    delattr(p,'sal')
    print(hasattr(p,'asl'))
    print(p.__dict__.get('level'))
    

    反射小练习:使用反射实现输入属性的名字就可以执行类或对象中的方法。

    class Movie:
        def input_cmd(self):
            print('输入命令:')
            while True:
                cmd = input('请输入方法名').strip()
                if hasattr(self,cmd):
                    method = getattr(self,cmd)
                    method()
        def upload(self):
            print('电影开始上传')
    
        def download(self):
            print('电影开始下载')
    
    movie_obj = Movie()
    movie_obj.input_cmd()
    

    魔法方法

    魔法方法(类的内置方法):凡是在类内部定义,以__开头__结尾都称之为魔法方法,又称类的内置方法,
    会在某些条件成立的情况下触发。
    __init__:在调用类时触发。
    __str__:会在打印对象时触发,必须要return一个字符串类型的值。
    __str__应用:打印一个列表等等。
    __del__:会在程序执行结束时触发,对象销毁,该方法会在最后被执行和其定义的位置无关。
    __getattr__:会在对象.属性时,属性没有的情况下触发,如果没有默认返回None,我们可以加return 我们想要的值。
    __getattribute__:不管属性有没有都会触发,如果和__getattr__同时出现,则只执行前者(__getattribute__)
    __setattr__:会在对象.属性 = 属性值 时触发,出发时外部的对象添加属性赋值就没用了,属性赋值在内部进行。
    __call__:会在对象被调用时触发。
    __new__:会在__init__执行前触发,真正的实例化对象就是通过object类中的__new__进行的,__new__会创建一个空的实例化对象。

    class Foo(object):
    
        def __new__(cls, *args, **kwargs):
            print(cls)
            return object.__new__(cls)#通过object产生一个空对象
    
        def __init__(self):
            print('在调用类时触发。。。')
    
        def __str__(self):
            print('在打印时触发。。。')
            return 'xiaohua'
    
        def __del__(self):
            print('对象被销毁前执行该方法')
    
        def __getattr__(self, item):
            print('会在对象.属性时,属性没有的情况下触发')
            print(item)
            #默认返回None,若想打印属性的结果,必须return一个值
            return 1
    
        def __setattr__(self, key, value):
            print('会在对象.属性 = 属性值 时触发...')
            print(key,value)
            print(type(self))
            print(self,111)
            self.__dict__[key] = value
    
        def __call__(self, *args, **kwargs):
            print(self)
            print('调用对象时触发该方法...')
    
    foo_obj = Foo()
    print(foo_obj.__class__)
    foo_obj.x = 10
    #print(foo_obj.x)
    print(foo_obj)
    

    小练习:使用魔法方法和open,实现with open的功能。

    class MyFile:
        def __init__(self,file_name,mode = 'r',encoding = 'utf8'):
            self.file_name = file_name
            self.mode = mode
            self.encoding = encoding
    
        def file_open(self):
            self.f = open(self.file_name,self.mode,encoding=self.encoding )
    
        def file_read(self):
            res = self.f.read()
            print(f'''
            当前文件名称:{self.file_name}
            当前文件数据:{res}
            ''')
    
        def __del__(self):
            self.f.close()
            print('文件关闭成功')
    
    f = MyFile('biji.txt')
    f.file_open()
    f.file_read()
    

    单例模式

    单例模式指的是单个实例,实例指的时调用类产生的对象。

    ​ 实例化多个对象会产生不同的内存地址,单例可以让所有调用者, 在调用类产生对象的情况下都指向同一份内存地址。 例如: 打开文件。

    ​ 单例的目的:
    ​ 为了减少内存的占用。

    class File:
        __instance = None
        # 单例方式1
        @classmethod
        def singleton(cls,file_name):
            if not cls.__instance:
                obj = cls(file_name)
                cls.__instance = obj
            return cls.__instance
    
        def __init__(self,file_name,mode='r',encoding = 'utf8'):
            self.file_name = file_name
            self.mode = mode
            self.encoding = encoding
    
        def open(self):
            self.f = open(self.file_name,self.mode,encoding=self.encoding)
    
        def read(self):
            res = self.f.read()
            print(res)
    
        def close(self):
            self.f.close()
    
    file1 = File.singleton('biji.txt')#此处必须要调用这个方法才行
    print(file1)
    file2 = File.singleton('biji.txt')
    print(file2)
    
    class File:
        __instance = None
        # 单例方式2
        def __new__(cls, *args, **kwargs):
            if not cls.__instance:
                cls.__instance = object.__new__(cls)
            return cls.__instance
    
        def __init__(self,file_name,mode='r',encoding = 'utf8'):
            self.file_name = file_name
            self.mode = mode
            self.encoding = encoding
    
        def open(self):
            self.f = open(self.file_name,self.mode,encoding=self.encoding)
    
        def read(self):
            res = self.f.read()
            print(res)
    
        def close(self):
            self.f.close()
    
    file1 = File('biji.txt')#此处必须要调用这个方法才行
    print(file1)
    file2 = File('biji.txt')
    print(file2)
    
  • 相关阅读:
    什么是索引?怎么创建索引?索引的使用原则?
    Cookie和Session的区别
    HashMap、Hashtable、ConcurrentHashMap的原理与区别
    vxlogcfg vxlogcfg – 修改统一日志记录配置设置
    磁盘阵列RAID介绍及计算公式
    二叉树的最近公共祖先 递归
    LRU 缓存机制
    从前序与中序遍历序列构造二叉树 递归
    MySQL 数据结构常用命令
    Node.Js 搭建简单的 EggJs 示例项目
  • 原文地址:https://www.cnblogs.com/ghylpb/p/11663995.html
Copyright © 2020-2023  润新知