zoukankan      html  css  js  c++  java
  • 面向对象高级

    一.isinstance和issubclass

    1.isinstance():用来判断某个对象是不是某个类的实例。

    print(isinstance([],list)) #判断这个[]是不是一个列表
    
    True

    2.issubclass():用来判断一个类是不是另一个类的子类。

    print(list,object) #判断list这个类是不是object的子类
    
    True

    二.反射(自省)

    简单的来说反射就是对象要具备一种修正错误的能力,或者说通过字符串来操作属性就是反射。

    反射有以下几种方法:

    1. hasattr  判断是否存在某个属性

    2. getattr  获取某个属性的值

    3. setattr  设置某个属性的值

    4. delattr  删除某个属性

    以上几种方法的共同点都是通过字符串来操作属性的。反射操作的都是对象__dict__中的内容。

    class People:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    
    p1 = People('wangke', 25)
    
    print(hasattr(p1, 'name'))  # 判断p1是否存在name属性,存在返回True,不存在则返回False
    
    print(getattr(p1, 'aaa', None))  # 获取p1的name属性的值,如果没有该属性,则返回None
    
    setattr(p1, 'name', 'wk')  # 设置name属性的值,如果存在name则修改原值,如果不存在name,则添加该属性
    print(p1.name)
    
    delattr(p1,'name')  # 删除name属性
    # 需要编写一个CMD工具  这个工具可以支持两个命令 dir ,tasklist
    
    class CMD:
    
        def dir(self):
            print("列出当前文件夹目录....")
    
        def tasklist(self):
            print("查看任务列表.....")
    
    
    cmd = CMD()
    
    
    res = input("请输入指令:").strip()
    
    if hasattr(cmd,res):
        func = getattr(cmd,res)
        print(func)
        func()
    else:
        print("输入的指令不正确....")
    反射练习

    三.__str__方法

    这是python解释器的内置函数,当我们需要自定义打印显示的内容时,就需要去实现__str__方法。此方法vixu返回一个字符串,打印的结果就是返回的结果。

    class Student:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __str__(self):
            return 'name:%s,age:%s' % (self.name, self.age)  # 自定义打印的结果
    
    
    stu1 = Student('wangke', 25)
    
    print(stu1)  # name:wangke,age:25

    四.__del__方法

    此方法在当对象被从内存中删除时,会自动执行,或者手动删除对象时,也会自动执行。该方法也称为析构函数(分析构造并拆除对象)。

    什么时候使用__del__方法?

    简单的来说就是当程序运行结束时,需要做一些清理的操作,就是用__del__方法。(在python中,有自动内存管理机制,所以 python自己创建的数据不需要我们做任何操作。但是有一种情况:我们使用python打开了一个不属于python管理的数据,比如:打开了一个文件,这个文件一定是操作系统在打开,会占用系统内存,而python解释器无法操作系统内存。所以当你的python解释器运行结束后,文件依然处于打开状态,这时候就需要使用__del__来关闭系统资源)

    class File:
    
        def __init__(self, name, mode='rt', encoding='utf-8'):
            self.file = open(name, mode=mode, encoding=encoding)
    
        def read(self):
            self.file.read()
    
        def write(self, text):
            self.file.write(text)
    
        def __del__(self):  # 程序运行完,通知系统需要进行删除操作
            self.file.close()  # 通知系统关闭文件
    
    
    f1 = File('aaa')
    f2 = File('aaa', 'wt')
    f1.read()
    
    f2.write('1')

    五.exec(execute)方法

    exec作用时帮你解析执行python代码,并且将得到的名称,存储到指定的名称空间。它有三个参数:

    参数一:需要一个字符串对象,表示需要被执行的python语句

    参数二:一个字典,表示全局名称空间

    参数三:一个字典,表示局部名称空间

    如果三个参数同时存在,则会将字符串中包含的名称,解析后存到局部名称空间中。如果只有前俩个参数,则会存到全局名称空间中。

    # 创建一个字符串对象
    str1 = '''
    a = 1
    class Student:
        def __init(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        def learning(self):
            print('%s正在学习。。。' % (self.name))
    '''
    
    globals_dic = {}  # 创建全局名称空间
    
    locals_dic = {}  # 创建局部名称空间
    
    exec(str1, globals_dic, locals_dic)
    
    print(locals_dic)  # {'a': 1, 'Student': <class 'Student'>}
    
    stu1 = locals_dic.get('Student')()
    
    print(stu1)  # <Student object at 0x000002ABEE979908>

    六.元类

    元类指的是用于产生类的类,type就是元类。类也是一个对象,我们可以通过元类(type)来实例化产生一个类。

    创建类的三要素:

    1.类名,2.基类(元组的形式),3.类的名称空间

    class_name = 'People'  # 类名
    
    class_bases = (object,)  # 基类
    
    class_dic = {}  # 类的名称空间
    
    str1 = '''
    def foo():
        import time
        print('hello')
        name = 'wangke'
        age = 25
        time.sleep(2)
        print('name:%s age:%s' % (name,age))  
    '''
    
    res = exec(str1, {}, class_dic)
    print(class_dic)  # {'foo': <function foo at 0x000001DB604D2E18>}
    
    People = type(class_name, class_bases, class_dic)  # 创建类

    七.__call__方法

    对象后面加括号,触发执行__call__方法。

    注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()。

    class Foo:
    
        def __init__(self):
            pass
        
        def __call__(self, *args, **kwargs):
    
            print('__call__')
    
    
    obj = Foo() # 执行 __init__
    obj()       # 执行 __call__
    """
    
        __call__
    
        调用的意思
        在在对象被调用时 执行
    
        函数 类
    
    
        自定义元类 的目的
        1.可以通过__call__ 来控制对象的创建过程
        2.可以控制类的创建过程
    
    
    """
    
    # 自定义一个元类 元类也是一个类   但是需要继承type
    class MyMeta(type):
    
        # self 表示要创建对象的那个类(Person)  *args是调用Person类时传入的参数
        def __call__(self, *args, **kwargs):
    
            print("MyMte中的 call run'")
            print(self,*args,**kwargs)
    
            # 下面的三步是固定写法 一个模板 只要你需要控制对象的创建过程 就应该先把模板写出来
    
            # 1.创建空对象
            obj = object.__new__(self)
            # 2.调用初始化方法
            self.__init__(obj,*args,**kwargs)
            # self.__init__(obj)
            # 3.得到一个完整的对象
            return obj
    
    
    
    # 修改Person类的元类为MyMeta
    class Person(metaclass=MyMeta):
    
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def __call__(self, *args, **kwargs):
            print("call run...")
    
    
    #调用Person这个对象时 执行的是 Person的类(type)中__call__ 方法
    p = Person("张三疯",80)
    
    print(p)
    # 当调用对象时 会执行该对象所属类中的__call__方法
    # p()
    
    print(p.name)
    print(p.age)
    
    
    # class People:
    #     def __init__(self,name):
    #         self.name = name
    #     pass
    #
    #
    # p = People()
    # p.anme = 1
    View Code
    # 要控制类的创建过程 只要找到类所属的类 中的__init__即可
    
    
    class MyMeta(type):
    
        # self 刚建出来的类
        # 第二个 类的名字
        # 第三个 类的父类们 元组
        # 第四个 这个类传进来的名称空间
        def __init__(self,class_name,bases,namespace):
            print("============================")
            #print(self.__dict__)
            # 我要控制 类的名字  必须 是大写开头
            if not class_name.istitle():
                print("类名 必须大写开头...... ")
                # 该代码是主动抛出异常
                raise TypeError("类名 必须大写开头...... ")
            #要空类的创建 必须包含__doc__这个属性
            if not self.__doc__:
                raise TypeError("类中必须有文档注释.....")
    
            pass
    
    class Student(metaclass=MyMeta):   # Student = MyMeta("Student",(object,),{})
        """
            这是文档注释  可以通过__doc__来获取
            这是一个学生类
        """
    
        # 在类的__init__中可以控制该类对象的创建过程
        def __init__(self,name):
            print("-----------------------")
            print(self.__dict__)
            self.name = name
    
    print(Student.__doc__)
    
    # 元类使用总结:
    """
    元类是用于创建类的类
    学习元类是为了 能控制类的创建过程 以及 类实例化对象的过程
    一.
    控制类的创建过程
        1.创建一个元类 (需要继承type)
        2.覆盖__init__方法  该方法 会将新建的类对象  类名 父类们 名称空间 都传进来 ,
            可以利用这些信息在做处理
        3.对于需要被控制的类 需要指定metaclass 为上面的元类 
        
    二.
    控制类实例化对象的过程
         1.创建一个元类 (需要继承type)
         2.覆盖__call__方法 会将 正在实例化对象的类  调用类是传入的参数  都传进来
         3.在__call__方法中 必须要先编写模板代码
            3.1创建空对象
            3.2调用类的__init__方法来初始化这个空对象
            3.3返回该对象
         4.加入你需要控制的逻辑 
         
    类的三个组成部分
    类名 父类们 名称空间
    
    元类 -> 实例化产生 -> 类 -> 实例化产生 -> 对象
    控制类的创建过程
    class My(type):
        def __call__(self, *args, **kwargs):
    
            #1.先造出Student的空对象
            obj = self.__new__(self)
            #2.为该空对象初始化独有的属性
            self.__init__(obj, *args, **kwargs)
            #3.返回一个初始化好的对象
            return obj
    
    
    class Student(metaclass=My):
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    
    obj = Student('wangke', 25, 'male')
    
    print(obj.__dict__)
    控制类的实例化过程

    八.单例模式

    单例模式是一种设计模式(套路)。一个类如果只有一个实例,那么该类称为单例。它可以节省内存空间。

    class My(type):
        obj = None
        def __call__(self, *args, **kwargs):
            if not My.obj:
                obj = object.__new__(self)
                self.__init__(obj, *args, **kwargs)
                My.obj = obj
            return My.obj
    
    
    class People(metaclass=My):
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        @classmethod
        def get(cls):
            if not cls.obj:
                obj = cls('wangke', 25)
                cls.obj = obj
    
            return cls.obj
    
    
    # p = People.get()  # <__main__.People object at 0x0000024845849978>
    # p0 = People.get()  # <__main__.People object at 0x0000024845849978>
    # print(p)
    # print(p0)
    p1 = People('wangke', 25)
    p2 = People('wangke', 25)
    print(p1)  # <__main__.People object at 0x000002154DD19A20>
    print(p2)  # <__main__.People object at 0x000002154DD19A20>
    单例模式
    class MyMeta(type):
    
        obj = None
        def __call__(self, *args, **kwargs):
            if not MyMeta.obj:
                obj = object.__new__(self)
                self.__init__(obj,*args,**kwargs)
                MyMeta.obj = obj
            return MyMeta.obj
    
    
    #打印机类
    class  Printer(metaclass=MyMeta):
        """
        这是一个单例类 请不要直接实例化 使用get方法来获取实例
        """
    
        obj = None
        def __init__(self,name,brand,type):
            self.name = name
            self.brand = brand
            self.type = type
    
        def printing(self,text):
            print("正在打印 %s"  % text)
    
        # 通过该方法来获取对象 可以保证只有一个对象
        # 但是这还不够 因为 还是可以通过调用类产生新对象
        # 就应该使用元类 来控制实例化的过程 __call__
        # 在__call__ 中编写代码 保证每次调用call 都返回同一个实例 即可
    
        @classmethod
        def get_printer(cls):
            if not cls.obj:
                obj = cls("ES005","爱普生","彩色打印机")
                cls.obj = obj
                print("创建了新的对象")
    
            return cls.obj
    
    # 以下三个对象 的数据完全相同 但是却 占用三分内存空间
    # p1 = Printer("ES005","爱普生","彩色打印机")
    # p2 = Printer("ES005","爱普生","彩色打印机")
    # p3 = Printer("ES005","爱普生","彩色打印机")
    
    # 现在要处理问题就是  如何能够限制该类 只能实例化一个对象
    
    p = Printer.get_printer()
    print(p)
    
    p = Printer.get_printer()
    print(p)
    
    p = Printer.get_printer()
    print(p)
    
    p = Printer.get_printer()
    print(p)
    
    p1 = Printer("ES005","爱普生","彩色打印机")
    p2 = Printer("ES005","爱普生","彩色打印机")
    
    print(p1)
    print(p2)
    # print(p1,p2,p3)
    
    
    # p1.printing("一本小说....")
    View Code
  • 相关阅读:
    要看的博客
    sleep(0)的妙用
    Spring Cloud:Eureka的多网卡IP选择问题
    SpringBoot整合swagger
    springboot整合redis(注解形式)
    RSA非对称加密
    java split(regex,limit) 使用记录
    windows git支持arc命令
    eclipse安装反编译插件
    使用@Validated分组遇到的坑
  • 原文地址:https://www.cnblogs.com/wangke0917/p/10145363.html
Copyright © 2011-2022 走看看