zoukankan      html  css  js  c++  java
  • 多态 鸭子类型 反射 内置方法(__str__,__del__) 异常处理

    '''
    1什么是多态
        多态指的是同一种/类事物的不同形态
    
    2 为何要有多态
        多态性:在多态的背景下,可以在不用考虑对象具体类型的前提下而直接使用对象
        多态性的精髓:统一
        多态性的好处:
            1增加了程序的灵活性:
                以不变应万变,不论对象千变万化,使用者都是同一种形式去调用
            2增加了程序可扩展性
                继承一个Animal类创建一个新的类,使用者无需更改自己的代码,还是用原来的方式调用
    3 如何用多态
    
    '''
    '''
    class Animal:
        def speak(self):
            pass
    
    class People(Animal):
        def speak(self):
            print('say hello')
    
    class Dog(Animal):
        def speak(self):
            print('wang wang wang')
    
    class Pig(Animal):
        def speak(self):
            print('哼哼哼')
    
    obj1=People()
    obj2=Dog()
    obj3=Pig()
    
    # obj1.speak()
    # obj2.speak()
    # obj3.speak()
    
    
    def speak(animal):
        animal.speak()
    
    speak(obj1)
    speak(obj2)
    speak(obj3)
    # say hello
    # wang wang wang
    # 哼哼哼
    
    
    多态性带来的好处,比如python的系列类型有多种形态:字符串,列表,元组,多态性提现下
    
    s1='hello'
    l1=[1,2,3]
    t1=(1,2)
    
    我们可以在不考虑三者类型的前提下使用是 s l t
    print(len(s1)) #s1.__len__()
    print(len(l1)) #l1.__len__()
    print(len(t1))  #t1.__len__()
    
    '''
    # import abc
    #
    #
    # class Animal(metaclass=abc.ABCMeta):
    #     @abc.abstractmethod
    #     def speak(self):
    #         pass
    #
    #     @abc.abstractmethod
    #     def run(self):
    #         pass
    
    
    # Animal() 父类只是用来建立规范的,不能用来实例化的,更无须实现内部的方法
    # 只是规定有这些方法或者属性 具体属性或者方法在子类中具体实现
    # class People(Animal):
    #     def speak(self):
    #         print('say hello')
    #
    #     def run(self):
    #         pass
    #
    #
    # class Dog(Animal):
    #     def speak(self):
    #         print('汪汪汪')
    #
    #     def run(self):
    #         pass
    #
    #
    # class Pig(Animal):
    #     def speak(self):
    #         print("哼哼哼")
    #
    #     def run(self):
    #         pass
    #
    #
    # obj = People()
    # obj2 = Dog()
    # obj3 = Pig()
    
    
    # 上面是强制性的,父类有的方法,子类必须有
    
    # obj.speak()
    # obj2.speak()
    # obj3.speak()
    # say hello
    # 汪汪汪
    # 哼哼哼
    
    # python 崇尚鸭子类型
    # 利用标准库中定义的各种‘与文件类似’的对象,尽管这些对象的工作方式像文件,但他们没有继承内置文件对象的方法
    # class Disk:
    #     def read(self):
    #         print('Disk read')
    #
    #     def write(self):
    #         print('Disk write')
    #
    #
    # class Memory:
    #     def read(self):
    #         print('Mem write')
    #
    #     def write(self):
    #         print('Mem write')
    #
    #
    # class Cpu:
    #     def read(self):
    #         print('Cpu read')
    #
    #     def write(self):
    #         print('Cpu write')
    
    
    # obj=Disk()
    # obj2=Memory()
    # obj3=Cpu()
    #
    # obj.read()
    # obj2.read()
    # obj3.read()
    
    # Disk read
    # Mem write
    # Cpu read
    
    
    # 反射: 通过字符串来反射/映射到对象/类的属性上
    #         (之前是 xx.属性来映射或反射到类或对象的属性上)
    # class People:
    #     def __init__(self,name,age):
    #         self.name=name
    #         self.age=age
    #     def run(self):
    #         print('%s is running' %self.name)
    #
    #
    # obj=People('egon',18)
    
    # print(obj.__dict__) #{'name': 'egon', 'age': 18}
    # print(obj.name) #obj.__dict__['name']  #egon
    # obj.name="EGON" #obj.__dict__['name']="EGON"
    # del obj.name  #del obj.__dict__['name']
    # print(obj.__dict__) #{'age': 18}
    # obj.sex='male' #obj.__dict__['sex']='male'
    
    # print(hasattr(obj, 'name')) #True  'name' in obj.__dict__
    
    # print(getattr(obj, 'name'))  #拿到值egon obj.__dict__['name']
    # print(getattr(obj, 'xx', None))  #拿值 没有则返回None obj.__dict__['xx']
    
    # setattr(obj, 'name', 'EGON')  #obj.__dict__['name']='EGON'  #EGON 有name就改值
    # setattr(obj,'xxx','2222') #{'name': 'egon', 'age': 18, 'xxx': '2222'}  没有就创建
    # print(obj.name)
    # print(obj.__dict__)
    
    # delattr(obj,'name')
    # print(obj.__dict__)  #{'age': 18}
    
    # import os
    # os.remove
    # print(hasattr(os,'remove'))  #True
    
    
    # class Ftp:
    #     def get(self):
    #         print('get')
    #     def put(self):
    #         print('put')
    #
    #     def login(self):
    #         print('login')
    #
    #     def run(self):
    #         while True:
    #             cmd=input(">>>: ").strip()  #cmd='get'
    #             if hasattr(self,cmd): #cmd in self.__dict
    #                 method=getattr(self,cmd) #self.__dict__['cmd']
    #                 method()
    #
    #             else:
    #                 print('输入方法不存在')
    #
    #
    # obj=Ftp()
    # obj.run()
    
    
    # 内置方法:
    # __str__:在对象被打印时自动触发,可以用来定义对象被打印时的输出信息
    # 注意:必须返回一个字符串类型的值
    # class People:
    #     def __init__(self,name,age):
    #         self.name=name
    #         self.age=age
    #
    #     def __str__(self):
    #         # print('run.....')
    #         return  'name: %s age:%s'%(self.name,self.age)
    # obx=People('egon',18)
    # print(obx)   #print(obx.__str__())
    # name: egon age:18
    
    # obj1=list([1,2,3])
    # print(obj1)  #[1, 2, 3]
    
    
    # __del__:在对象被删除时先自动触发该方法,可以用来回收对象以外其他相关资源,比如系统资源
    # class Foo:
        # def __init__(self,x,filepath,encoding='utf-8'):
        #     self.x=x
        #     self.f=open(filepath,'rt',encoding=encoding)
        #
        # def __del__(self):
        #     print('run.....')
        #     #回收对象关联的其他资源
        #     self.f.close()
    
    # obj=Foo(1,'a.txt')
    # print('========》') 1程序结束了会把占用的内存空间回收掉 删除对象 最后执行__del__回收对象关联的其他资源
        # ========》
        # run.....
    
    
    # obj=Foo(1,'a.txt')  #程序没结束提前删除 会先执行__del__ 回收对象关联的其他资源
    # del obj
    # print('========》')
        # run.....
        # ========》
    
    
    '''
    1 什么是异常处理
        异常是错误发生的信号,一旦程序出错就会产生一个异常,如果该异常
        没有被应用程序处理,那么该异常就会被抛出来,程序的执行也随之终止
        
        异常包含三个部分:
            1 traceback异常的追踪信息
            2 异常的类型
            3 异常的信息
        
        错误分为两大类:
            1 语法上的错误:在程序运行前就应该立即修正
            2 逻辑上的错误
        
    2 为和要有异常处理
        避免程序因为异常而崩溃,所以在应用程序中应该对异常进行处理,从而增强程序的健壮性
    
    3 如何异常处理
    try:
        代码1 
        代码2   #抛出一种异常    #!!!!下面代码块不会执行
        代码3
        。。。
    except NameError:   #捕获异常也只会捕获一种异常下面的except分支不会执行(像if 。。elif...一样)
        当抛出的异常是NameError时执行的子代码块
    except....:    
        pass
    except...:
        pass
    else:         
        pass    #else的子代码块会在被检测的代码块没有异常的情况下执行
    finally:   
        pass     #无论被检测的代码有没有异常都会执行
    
    '''
    # 语法错误
    # print('asdjfkj'
    # 1 常见的逻辑错误导致的异常
    # age=input('>>: ').strip()
    # print(age>10)    #TypeError
    
    # for  i in  10: #TypeError
    #     pass
    # import os  #AttributeError
    # os.xxx
    # 1/0  #ZeroDivisionError
    
    # print('====1')
    # print('====2')
    # print('====3')
    # # l=[1,2,3]
    # # l[100]   #IndexError
    # print('====4')
    # # d={'x':1,'y':2}
    # # d['z']     #KeyError
    # print('====5')
    
    # 2.异常处理
    # 异常处理的单分支
    # try:
    #     print('=====1')
    #     print('=====2')
    #     print('=====3')
    #     d = {'x': 1, 'y': 2}
    #     d['z']  # KeyError
    #     print('=====4')
    #     l = [1, 2, 3]
    #     l[1000]  # IndexError
    #     print('=====5')
    # except IndexError:
    #     print('IndexError')
    # print('other code')
    
    # 异常处理的多分支
    # try:
    #     print('=====1')
    #     print('=====2')
    #     print('=====3')
    #     d = {'x': 1, 'y': 2}
    #     d['z']  # KeyError
    #     print('=====4')
    #     l = [1, 2, 3]
    #     l[1000]  # IndexError
    #     print('=====5')
    # except KeyError as e:
    #     print('KeyError',e)
    # except IndexError as e:
    #     print('IndexError',e)
    #
    # print('other code')
    
    # try:
        # print('=====1')
        #     print('=====2')
        #     print('=====3')
        #     d = {'x': 1, 'y': 2}
        #     # d['z']  # KeyError
        #     print('=====4')
        #     l = [1, 2, 3]
        #     l[1000]  # IndexError
        #     print('=====5')
        # except (KeyError,IndexError) as e: #except(里面多个错误捕获类型)
        #     print(e)
        # print('other code')
    
    # 万能异常类型Exception:可以匹配任意类型的异常
    # try:
    #     print('=====1')
    #     print('=====2')
    #     print('=====3')
    #     d = {'x': 1, 'y': 2}
    #     # d['z']  # KeyError
    #     # xxx
    #     print('=====4')
    #     l = [1, 2, 3]
    #     l[1000]  # IndexError
    #     print('=====5')
    # except IndexError as e:
    #     print('IndexError:', e)
    # except KeyError as e:
    #     print('KeyError:', e)
    # except Exception as e:
    #     print('Exception:',e)
    #
    # print('other code')
    
    # 主动触发异常
    # print('===>1')
    # print('===>2')
    # raise TypeError('类型错误')   #运行到这里就报错
    # print('===>3')
    
    # class People:
    #     def __init__(self,name,age):
    #         self.__name=name
    #         self.__age=age
    #
    #     def tell_info(self):
    #         print(self.__name,self.__age)
    #
    #     def set_info(self,name,age):
    #         if not isinstance(name,str):
    #             raise TypeError('名字必须是str类型')
    #         if not isinstance(age,int):
    #             raise TypeError('年龄必须是int类型')
    #         self.__name=name
    #         self.__age=age
    
    # obj=People('egon',18)
    # print(obj.__dict__)  # {'_People__name': 'egon', '_People__age': 18}
    # obj.tell_info()  #egon 18
    
    # obj.set_info('alex',123)
    # obj.tell_info()  #alex 123
    
    # 自定义异常类型(了解)
    # class MyException(BaseException):
    #     def __init__(self,msg):
    #         super().__init__()
    #         self.msg=msg
    #
    #     def __str__(self):   #在对象被打印时自动触发,可以用来定义对象被打印时的输出信息
    #         return '<%s>'%self.msg
    #
    # raise MyException('我自定义的异常')
    # # __main__.MyException: <我自定义的异常>
    
    # 断言
    print('上半部分,生产数据')
    l=[1,2,3,4,5]
    
    # if len(l)!=5:  #满足条件执行里面的 主动触发异常 下面代码不执行
    #     raise TypeError('类表长度必须为5')
    assert  len(l)==5   #相当于门槛,满足条件才执行下面的代码
    #AssertionError
    
    print('下半部分,处理数据')

    封装:封装的真谛在于明确地区分内外,封装的属性可以直接在内部使用,而不能被外部直接使用,然而定义属性的目的终归是要用,外部想要类隐藏的属性,需要我们为其开辟接口,让外部能够间接地用到我们隐藏起来的属性,意义:

      1封装数据:将数据隐藏起来这不是目的。隐藏起来然后对外提供操作该数据的接口,然后我们可以在接口附加对数据的操作限制,以此完成对数据属性操作的严格控制。

    class Teacher:
        def __init__(self,name,age):
            # self.__name=name
            # self.__age=age
            self.set_info(name,age)
    
        def tell_info(self):
            print('姓名:%s,年龄:%s' %(self.__name,self.__age))
        def set_info(self,name,age):
            if not isinstance(name,str):
                raise TypeError('姓名必须是字符串类型')
            if not isinstance(age,int):
                raise TypeError('年龄必须是整型')
            self.__name=name
            self.__age=age
    
    
    t=Teacher('egon',18)
    t.tell_info()
    
    t.set_info('egon',19)
    t.tell_info()
    View Code

      2封装方法:目的是隔离复杂度

        在编程语言里,对外提供的接口(接口可理解为一个入口),可以是函数,称为接口函数,这与接口的概念还不一样,接口代表一组接口函数的集合体。

    #取款是功能,而这个功能有很多功能组成:插卡、密码认证、输入金额、打印账单、取钱
    #对使用者来说,只需要知道取款这个功能即可,其余功能我们都可以隐藏起来,很明显这么做
    #隔离了复杂度,同时也提升了安全性
    
    class ATM:
        def __card(self):
            print('插卡')
        def __auth(self):
            print('用户认证')
        def __input(self):
            print('输入取款金额')
        def __print_bill(self):
            print('打印账单')
        def __take_money(self):
            print('取款')
    
        def withdraw(self):
            self.__card()
            self.__auth()
            self.__input()
            self.__print_bill()
            self.__take_money()
    
    a=ATM()
    a.withdraw()
    
    隔离复杂度的例子
    View Code

      3在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的

    #正常情况
    >>> class A:
    ...     def fa(self):
    ...         print('from A')
    ...     def test(self):
    ...         self.fa()
    ... 
    >>> class B(A):
    ...     def fa(self):
    ...         print('from B')
    ... 
    >>> b=B()
    >>> b.test()
    from B
     
    
    #把fa定义成私有的,即__fa
    >>> class A:
    ...     def __fa(self): #在定义时就变形为_A__fa
    ...         print('from A')
    ...     def test(self):
    ...         self.__fa() #只会与自己所在的类为准,即调用_A__fa
    ... 
    >>> class B(A):
    ...     def __fa(self):
    ...         print('from B')
    ... 
    >>> b=B()
    >>> b.test()
    from A
    View Code

    隐藏:在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)

      这仅仅只是一种变形操作且仅仅只在类定义阶段发生变形

      类中所有双下划线开头的名称如__x都会在类定义时自动变形成:_类名__x的形式。

    __delattr__() 删除属性前进行的操作需要继承super().__delattr__(属性)否则删除不了

    __del__() 删除对象前进行的操作 释放和对象相关的其他资源

    __delete__()删除对象的属性(属性是组合类型的 一个类的对象作为另外一个类的属性)

  • 相关阅读:
    Optional的使用
    Spring Boot 传送门
    MP(MyBatis-Plus)实现乐观锁更新功能
    实现数据逻辑删除的一种方案
    凹凸技术揭秘 · 基础服务体系 · 构筑服务端技术中枢
    凹凸技术揭秘 · 夸克设计资产 · 打造全矩阵优质物料
    凹凸技术揭秘·羚珑页面可视化·成长蜕变之路
    90%的开发都没搞懂的CI和CD!
    Devops与敏捷二者能否结合?
    优质单元测试的十大标准,你有遵循吗?
  • 原文地址:https://www.cnblogs.com/lakei/p/10753703.html
Copyright © 2011-2022 走看看