鸭子类型-类的约束-异常处理

封装,多态

python三大特性: 继承,封装,多态

多态:

python默认支持多态

一个事物可以拥有多种形态(一个变量名可以指向任何数据类型)

鸭子类型

python处处都是鸭子类型

两个类中定义的几个方法名相同,两个类就互为鸭子

class A:
    def add(self):
        print('增加')

    def delete(self):
        print('删除')

class B:
    def add(self):
        print('这也是增加')

    def delete(self):
        print('这也是删除')

    def update(self):
        pass

两个类中方法名一样,两个类虽然没有任何关系,但是隐形中遵循了一个标准:

1.统一标准,减少词汇量,建立了弱关联

2.A和B没有任何耦合性,但是可以产生关系A的对象使用B类的方法

super()方法

super可以执行非本方法的方法

super(指定类名,self)  跳过指定类名

super()是完全按照对象self所在类的mro的顺序执行的

class A:
    def func1(self):
        print('in A func1')

class B(A):
    def func1(self):
        super().func1()      #super(B,self).func1()  跳过B类,按照mro顺序执行
        print('in B func1')

class C(A):
    def func1(self):
        print('in C func1')

class D(B,C):
    def func1(self):
        super().func1()      #super(D,self).func1()  跳过D类,按照mro顺序执行
        print('in D func1')

obj = D()
obj.func1()
print(D.mro())    #mro顺序D B C A

结果:
in C func1
in B func1
in D func1

类的约束

指定一个强制的标准,强制子类要有父类规定的方,python提供两种解决方式:

方法一:在父类的方法中主动抛出异常(常用)   raise

class Payment:
    def pay(self,money):
        raise Exception('子类要定义pay方法!!!')

class Alipay(Payment):
    def pay(self,money):
        print('您用阿里支付了%s元' % money)

class QQpay(Payment):
    def pay(self,money):
        print('您用QQ支付了%s元' % money)

class Wechatpay(Payment):
    def pay(self,money):
        print('您用微信支付了%s元' % money)

class Applepay(Payment):
    def zhifu(self,money):          #没有用pay方法,在使用父类pyment中的pay方法中,会因为raise主动报错
        print('您用苹果支付了%s元' % money)

def pay(obj,money):                  # 统一了支付方式:归一化设计
    obj.pay(money)                   # obj2.pay(200)

obj2 = Applepay()
pay(obj2,200)

方法二:引用抽象类,接口类

制定一个规范,强制子类必须有一些方法,如果没有,在实例化的时候就会报错

from abc import ABCMeta,abstractmethod      #固定格式
class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self,money):
        pass

class Alipay(Payment):
    def pay(self,money):
        print('您用阿里支付了%s元' % money)

class QQpay(Payment):
    def pay(self,money):
        print('您用QQ支付了%s元' % money)

class Wechatpay(Payment):
    def pay(self,money):
        print('您用微信支付了%s元' % money)

class Applepay(Payment):
    def zhifu(self,money):
        print('您用苹果支付了%s元' % money)

def pay(obj,money):   # 统一了支付方式:归一化设计
    obj.pay(money)    # obj2.pay(200)

obj2 = Applepay()      #在实例化的时候会报错
pay(obj2,200)

异常处理

异常错误分类:

1.语法错误

2.逻辑错误

异常处理:先捕捉错误,再进行处理

异常处理的两种方式:

1.if

劣势:

   1)对于相同的错误类型,要用大量的重复代码处理异常

   2)如果异常种类较多,利用if,代码量会出现冗余

2.try except 异常处理

  1)单支

try:
    a = 1
    b = 2
    l1 = [1,2,3]
    l1[100]             #索引错误  执行except
    print(111)
    dic = {}
    print(dic['key'])    #key错误
    print(111)
except IndexError:
    print(666)

  2)多分支

try:
    a = 1
    b = 2
    l1 = [1,2,3]
    l1[100]                     #索引错误
    print(111)
    dic = {}
    print(dic['key'])          #key错误
    num = input('>>>')
    int(num)                    #值错误
    print(222)
except IndexError as e:    #可以不写 as e
    print(e)
except KeyError as e:
    print(e)
except ValueError as e:
    print(e)
print(666)

  3)万能异常

try:
except Exception

try:
    dic[num]()
    l1 = [1,2]
    l1[100]
except Exception:
    print(666)

结果:
666

  4)多分支+万能

如果只想将异常处理掉,对错误信息不关心,用万能异常.

如果需要根据不同的错误信息而执行不同的逻辑(分流),用多分支,或者多分支加万能异常.

while 1 :
    print("""
    1  登录
    2  注册
    3  转账
    4  存钱
    """)
    try:
        num = int(input('请输入选项'))
        dic[num]()
    except ValueError:           #当用户输入内容是非数字时
        print('请输入数字')  
    except KeyError:             #当用户输入内容超出现有序号时
        print('请输入正确序号')
    except Exception:            #出现其他未知错误时,万能异常处理,保证程序继续运行
        pass

  5) try except else

如果出现异常,就不执行else,不出现异常执行else

try:
    a                      #没有定义a,执行except进行异常处理,不执行else
    print(111)
    print(222)
except Exception:
    print(333)
else:
    print(666)
    
结果:
333

  6)try except (else) finally

finally 出不出现异常都执行,异常出现前执行finally

用途:

  关闭文件句柄,关闭数据库链接

  函数return之前能够执行finally代码

  在break之前能够执行finally代码

try:
    dic = {}
    dic[100]          #keyerror
except ValueError:
    print(333)
finally:
    print(666)         #在报错之前执行

    
def func():
    try:
        return 666
    finally:
        print(111)    #在return之前执行
func()


while 1:
    try:
        if 3 > 2:
            break
    finally:
        print(333)   #在break之前执行
        

  7) 主动抛出异常   raise

raise IndexError('超出索引范围')

  8)断言   

表示一个强硬的态度,不满足条件就直接报错

assert 条件   条件不成立就报错

class A:
    name = None
    def get(self):
        assert A.name is not None
        num = 123
        for i in range(10):
            num += i
        print(num)

obj = A()
# A.name = 'barry'     #当name为None时,会直接报错,当把'barry'传给name时,会执行for循环
obj.get()

  9) 自定义异常

出现的错误是python解释器没有定义的错误类型,自己手动定义

# 手机连接问题
class PhoneConnection(BaseException):
    pass
try:
    raise PhoneConnection('手机连接错误')    #主动抛出异常
except Exception as e:
    print(e)

 异常处理总结:

1.异常处理不能经常使用,耗费性能,异常处理的分支越多,越冗余

2.能用程序解决的问题,尽量用程序解决

3.start文件中禁止使用

异常处理的用法:

1.一些无法预知的错误,要用异常处理

2.如果程序此时需要通过if条件过滤掉很多不必要的因素,可以用异常处理

猜你喜欢

转载自www.cnblogs.com/sandy-123/p/10329531.html