• 面向对象高级


    一.多态

    1.什么是多态

      多态指的是一种是事物具备多种不同的形态

      官方版本:多个不同类对象可以响应同一个方法,产生不同的结果 

    例如:水  固态 气态 液态  
            co2 固态(干冰),气态co2

    ps:首先强调多态不是一种特殊的语法,而是一种状态,特性(既多个不同对象可以响应同一个方法,产生不同的结果)既多个对象有相同的使用方法

    2.使用多态的好处 

    对于使用者而言,大大的降低了使用难度

    3.多态的实现方式

      接口,抽象类,鸭子类型,其中简单的就是鸭子类型

    class Ji:
        def xiadan(self):
            print('下鸡蛋')
    
    class Ya:
        def xiadan(self):
            print('下鸭蛋')
    
    class E:
        def xiadan(self):
            print('下鹅蛋')
    
    j=Ji()
    y=Ya()
    e=E()
    
    def xiadan1(obj):
        obj.xiadan()
    
    xiadan1(j)
    xiadan1(y)
    xiadan1(e)
    多态的实现(鸭子类型)
    a = 10
    b = "10"
    c = [10]
    
    print(type(a))
    print(type(b))
    print(type(c))
    python中的多态

    二.内置的魔法函数

    1.isinstance(判断一个对象是不是某个类的实例)

    基本句式:isinstance(a,A)
    其中第一个参数表示要判断的对象
    第二个参数表示判断的类型
    eg:
    class A:
        pass
    a=A()
    print(isinstance(a,A))  # True

    2.issubclass(判断一个类是不是另一个类的子类)

    基本句式:issubclass(A,B)
    第一个参数表示要判断的子类
    第二个参数表示父类
    eg:
    class B:
        pass
    
    class A(B):
        pass
    
    print(issubclass(A,B))  # True

    3.__str__

    __str__会在对象被转化为字符传时执行,转换的结果时这个函数的返回值

    使用场景:可以利用该函数来自定义对象的打印格式

    class  Person:
    
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def __str__(self):
    
            return "这是一个person对象 name:%s age:%s" % (self.name,self.age)

    4.__del__

    析构方法,当对象在内存中被释放时,自动触发执行。即(手动删除对象时立马执行,或是程序运行结束时也会自动执行 )

    使用场景:当你的对象在使用过程中打开了不属于解释器的资源如:文件,网络端口

    class Foo:
    
        def __del__(self):
            print('执行我啦')
    
    f1=Foo()
    del f1
    print('------->')
    
    #输出结果
    执行我啦
    ------->
    基本使用
    当程序结束时,python只会回收自己的内存空间,即用户态内存,而操作系统的资源则没有被回收,这就需要我们定制__del__,在对象被删除前向操作系统发起关闭数据库链接的系统调用,回收资源,这就类似于文件处理一般:
    f=open('a.txt') #做了两件事,在用户空间拿到一个f变量,在操作系统内核空间打开一个文件
    del f #只回收用户空间的f,操作系统的文件还处于打开状态
    
    #所以我们应该在del f之前保证f.close()执行,即便是没有del,程序执行完毕也会自动del清理资源,于是文件操作的正确用法应该是
    f=open('a.txt')
    读写...
    f.close()

    5.__call__

    使用场景:在调用对象时自动执行,(既对象加括号)

    class A:
        def __call__(self, *args, **kwargs):
            print("call run")
            print(args)
            print(kwargs)
    
    a = A()
    a(1,a=100)

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

    6.__slots__

    __slots__是什么:是一个类变量,变量值可以是一个列表,元组或者是可跌代对象,也可以是一个字符串(意味着所有的实例化只能有一个数据属性)

    __slots__的作用:做为一个内存优化的工具

    __slots__优化的原理:将原本不固定的属性数量固定了

    class Person:
    
        __slots__ = ["name"]
        def __init__(self,name):
            self.name = name
    
    p =  Person("jck")
    
    # 查看内存占用
     print(sys.getsizeof(p))
     p.age = 20 # 无法添加 报错
    
    # dict 没有了
    print(p.__dict__)  # 报错 AttributeError: 'Person' object has no attribute '__dict__'

    7.getattr,setattr,delattr

    class Foo:
        x=1
        def __init__(self,y):
            self.y=y
    
        def __getattr__(self, item):
            print('----> from getattr:你找的属性不存在')
    
    
        def __setattr__(self, key, value):
            print('----> from setattr')
            # self.key=value #无限递归了
            # self.__dict__[key]=value #应该使用它
    
        def __delattr__(self, item):
            print('----> from delattr')
            # del self.item #无限递归了
            self.__dict__.pop(item)
    
    #__setattr__添加/修改属性会触发它的执行
    f1=Foo(10)
    print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
    f1.z=3
    print(f1.__dict__)
    
    #__delattr__删除属性的时候会触发
    f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作
    del f1.a
    print(f1.__dict__)
    
    #__getattr__只有在使用点调用属性且属性不存在的时候才会触发
    f1.xxxxxx

    ps:getattribute该函数也是用来获取属性的,在获取的属性时如果存在getattribute则先执行该函数,如果没有拿到属性则继续调用getattr函数,如果拿到则直接返回

    8.__setitem__,__getitem,__delitem__

    class A:
        def __getitem__(self, item):
            print("__getitem__")
            return self.__dict__[item]
    
        def __setitem__(self, key, value):
            print("__setitem__")
            self.__dict__[key] = value
    
        def __delitem__(self, key):
            del self.__dict__[key]
            print("__delitem__")
    
    
    a = A()
    a.name = "jack"
    a["name"] = "jack"
    print(a["name"])
    del a["name"]
    print(a["name"])
    执行时机:
           getitem 当你用中括号去获取属性时 执行
           setitem  当你用中括号去设置属性时 执行
           delitem 当你用中括号去删除属性时 执行
            

    9.运算符重载

    当我们在使用某个符号时,python解释器都会为这个符号定义一个含义,同时调用对应的处理函数, 当我们需要自定义对象的比较规则时,就可在子类中覆盖 大于 等于 等一系列方法....

    class Student(object):
        def __init__(self,name,height,age):
            self.name = name
            self.height = height
            self.age = age
    
        def __gt__(self, other):
            # print(self)
            # print(other)
            # print("__gt__")
            return self.height > other.height
    
        def __lt__(self, other):
            return self.height < other.height
    
        def __eq__(self, other):
            if self.name == other.name and  self.age == other.age and self.height == other.height:
                return True
            return False
    
    
    
    stu1 = Student("jack",180,28)
    stu2 = Student("jack",180,28)
    
    
    print(stu1 < stu2)
    print(stu1 == stu2)
    运算符重载

    ps:上述代码中,other指的是另一个参与比较的对象

       大于和小与只要实现一个即可,符号如果不同,解释器会自动交换两个对象的位置

    10.迭代器协议

    class MyRange:
    
        def __init__(self,start,end,step):
            self.start = start
            self.end = end
            self.step = step
    
        def __iter__(self):
            return self
    
        def __next__(self):
            a = self.start
            self.start += self.step
            if a < self.end:
                return a
            else:
                raise StopIteration
    
    for i in MyRange(1,10,1):
        print(i)
    
    ps:迭代器是具有__iner__方法和__next__方法的对象,我们可以为对象增加这2个方法来让对象变成迭代器

    11.上下文管理

    上下文 context:指的是一段话的含义要参照当前的场景,即上下文,在python中上下文可以理解成一个代码区间,一个范围,例如:with open 打开的文件只在这个上下文中有效

    上下文管理中涉及到的两种方法:

      1.__enter__:表示进入上下文(进入某个场景)

      2.__exit__:表示退出上下文(退出某个场景)

    当执行with 语句时,会先执行enter ,
    
    当代码执行完毕后执行exit,或者代码遇到了异常会立即执行exit,并传入错误信息
    
    包含错误的类型.错误的信息.错误的追踪信息 
    ps:    enter 函数应该返回对象自己 
            exit函数 可以有返回值,是一个bool类型,用于表示异常是否被处理,仅在上下文中出现异常有用
            如果为True 则意味着,异常以及被处理了 
            如果为False,异常未被处理,程序将中断报错

    __exit__()中的三个参数分别代表异常类型,异常值和追溯信息,with语句中代码块出现异常,则with后的代码都无法执行

    class Open:
        def __init__(self,name):
            self.name=name
    
        def __enter__(self):
            print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('with中代码块执行完毕时执行我啊')
            print(exc_type)
            print(exc_val)
            print(exc_tb)
    
    
    
    with Open('a.txt') as f:
        print('=====>执行代码块')
        raise AttributeError('***着火啦,救火啊***')
    print('0'*100) #------------------------------->不会执行
    View Code

    如果__exit()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行

    class Open:
        def __init__(self,name):
            self.name=name
    
        def __enter__(self):
            print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('with中代码块执行完毕时执行我啊')
            print(exc_type)
            print(exc_val)
            print(exc_tb)
            return True
    
    
    
    with Open('a.txt') as f:
        print('=====>执行代码块')
        raise AttributeError('***着火啦,救火啊***')
    print('0'*100) #------------------------------->会执行
    View Code
  • 相关阅读:
    51nod1278 相离的圆
    CodeForces
    SPOJ
    51nod 1040(欧拉函数)
    51nod1009 51nod1042(数位dp)
    51nod1264 线段相交
    51nod1050 循环数组最大子段和
    Spark SQL UDF示例
    Spark SQL官网阅读笔记
    Spark RDD
  • 原文地址:https://www.cnblogs.com/z929chongzi/p/11264986.html
Copyright © 2020-2023  润新知