面向对象
类:面向对象
-
面向对象三大特性:继承 多态 封装
-
类:
- 每个实例化的对象都封装了类中相同的属性和方法,类是一个相似功能的结合体,
- 对象:类名加()就是一个对象,类中的属性就是变量
-
实例化:当执行类名加括号时就是实例化的过程
- 实例:就是将对象赋值给变量
-
面向对象编程,函数式编程,统称面向过程式编程
-
面向过程式编程好处:
-
优点:出色的完成你之前布置的所有需求
-
缺点:但凡更改或者增加一条需求,可能整个项目都会随之改变
-
类的结构:
-
类的调用:
-
class Student: #构建学生类 daily = '学习' #变量在类中称为: 属性,静态属性 , 静态字段 enamination = '考试' def work(self): #函数在类中称为:方法,动态方法, 动态属性 print('每天要上课') def homework(self): print('家庭作业') #类名的角度调用类中的属性: Student.cloth = "校服" #增 del Student.cloth #删 Student.enamination = "不考试" #改 print(Student.enamination) #查 Student.work(44) #工作中不使用
-
self 方法传值:
-
#实例化对象时发生三件事: # 1.在内存中创建一个对象空间 # 2.类名()自动执行__init__方法,并将这个对象空间(参数作为实参)传给self参数 # 3.执行__init__方法里面的代码,给对象空间封装其属性 #self 就是类中方法的第一个位置参数, #如果通过对象执行此方法,解释器就自动将此对象空间当做实参传给,self #约定俗称:类中的方法,第一个参数一般都设置成self class Student: #构建学生类,开启一个空间 daily = '学习' #静态属性,类的属性 enamination = '考试' def __init__(self,name,aex,hobby): #双下方法 self接受的是obj实例化对象,封装属性 self.name = name #name = '海洋' self.aex = aex self.hobby = hobby def work(self,color): #动态方法,类的方法 self.color = color print(f"{self.name}每天要上课'") #利用self对象空间,调用name属性 def homework(self): print('家庭作业') # haiyang = Student('海洋',18,'台球') #开辟一个haiyang空间,将参数传给self.name # junli = Student('俊丽',18,'吃') # print(haiyang.__dict__) # print(junli.__dict__) #在任何地方都可以给对象封装属性 haiyang = Student('海洋',18,'台球') #haiyang对象 实例化,空间中存放着类指针 haiyang.work("黑色") #可以在动态方法中添加属性 print(haiyang.__dict__) #不可以在实例化里面修改静态属性 # haiyang = Student('海洋',18,'台球') # haiyang.daily = "dada" #不能修改,这样写没有修改类中的静态属性,而是在自己空间中添加 # print(haiyang.daily) #只能查看,不能修改类中的静态方法 #obj = Student() #实例化时开启一个空间,类名() 这是一个实例化过程,实例化一个对象 # obj.age = '29' #增 # del obj.haha #删 # obj.sex = '女' #改 # print(obj.n) #查看单个属性 # print(obj.__dict__) #查看全部属性,返回字典
-
类添加属性和静态属性不可修改:
-
class A: address = "哒哒" def __init__(self,name): self.name = name def func(self): if self.name == 'aa': self.skins = "海洋" def func1(self): print(self.__dict__) A.aaa = "俊丽" #在外面封装属性 # obj = A("aa") # respons = input("输入1进行修改") # if respons == "1": # obj.dudu = "海洋" #在内部封装属性 # obj = A("aa") # obj.func() # print(obj.__dict__) obj = A('aa') A.func1(obj) print(A.__dict__) def obj.address #单项不可逆 #对象与对象之间互相独立 #对象如果查询一个属性:对象空间---->类空间---->父类空间 #类查询一个属性:类空间----->父类空间
-
依赖关系:
-
#类与类之间,将一个类的类名或者对象传给另一个类的方法中(当实参传) class Elephant: #大象类 def __init__(self,name): self.name = name def open(self,ref1): print(f"大象{self.name}默念三声:开门") ref1.open_door() def close(self,ref1): print(f"大象{self.name}默念三声:关门") ref1.close_door() class Refrigerator: #冰箱类 def __init__(self,name): self.name = name def open_door(self): print(f'{self.name}冰箱门被打开了') def close_door(self): print(f'{self.name}冰箱门被关上了') haiyang = Elephant('海洋') ref = Refrigerator('海尔') haiyang.open(ref) haiyang.close(ref)
-
组合关系:
-
#将一个类的对象封装成另一个类的对象的属性 #一个类的方法只能有此类的对象去调用‘ #一个类的方法的第一个self只接受此类的对象 class Boy: def __init__(self,name): #双下方法,自动执行,封装属性 self.name = name def meet(self,girl_friend = None): self.girl_friend = girl_friend def have_diner(self): #self = wu对象空间 if self.girl_friend: print(f"{self.name}请{self.girl_friend.name}一起吃饭") self.girl_friend.co(self) #等同于flower.co,将self传给co self else: print(f"一人吃饭") class Girl: def __init__(self,name,age): self.name = name self.age = age def co(self,boy_friend): #self = flower print(f"{boy_friend.name}和{self.name}一起溜达") haiyang = Boy('海洋') flower = Girl('俊丽',18) haiyang.meet(flower) #给meet传flower haiyang.have_diner()
-
依赖和组合:
-
class Game(): # 英雄类 def __init__(self, name, ad, hp): self.name = name self.ad = ad self.hp = hp def eauit_weapon(self, wea): # wea == great_sword self.weapon = wea # 组合:给盖伦这个对象封装了一个为wrapon属性 class Weapon: # 武器类 def __init__(self, name, ad): self.name = name self.ad = ad def weapon_attack(self, p1, p2): p2.hp = p2.hp - self.ad print(f"{p1.name}利用{self.name}给了{p2.name}一下,{p2.name}还剩{p2.hp}滴血") gailun = Game('盖伦', 10, 100) # 实例化人物 jianhao = Game('赵信', 20, 90) great_sword = Weapon('大宝剑', 30) # 实例化武器 spear = Weapon('红缨枪', 40) gailun.eauit_weapon(great_sword) # 依赖关系 gailun.weapon.weapon_attack(gailun, jianhao) # 给组合传参
继承:
-
继承,子类继承父类的属性和方法,实现代码的重用,减少代码的编写
-
继承:
-
优点:
- 节省代码,增强耦合性,代码规范
-
缺点:
-
类的耦合性继承要少用
-
可读性差,拍错难,容易出现意料之外的错误
-
-
-
单继承:
-
子类以及对象可以调用父类的属性或者方法,不能增删改
-
子类中如果有此属性,不找父类
-
super方法:用于调用父类
-
class Animal: live = "生命" def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def eat(self): # print(self) print("动物吃饭") class Person(Animal): def __init__(self,name,age,sex,hobby): #方法1 #调用Animal的双下方法 #Animal.__init__(self,name,age,sex) #方法2 #super方法,可以不写(),默认(Person, self) super(Person, self).__init__(name,age,sex) self.hobby = hobby def eat(self): print("人类吃法") super().eat() #调用父类方法 p1 = Person("海洋",18,'男','台球') print(p1.__dict__) p1.eat() #调用子类eat方法
-
-
多继承:
-
python2.2之前:都是经典类,
-
python2.2至python2.7之间存在两种类型:经典类,新式类
-
python3 只有新式类 默认继承 class A(object)
-
经典类:基类不继承object,
- 遵循深度优先原则
- 深入的规则是从左至右,从左边一直找到最底层,在从最底层一层一层往回找
-
新式类:基类必须继承object
- 遵循mro算法,mro依赖于c3算法
-
-
多继承示例和算法:
-
class God: #神仙 def __init__(self,name): self.name = name def fly(self): print("会飞") def climb(self): print("神仙也要爬树") class Monkey: #猴子 def __init__(self,sex): self.sex = sex def climb(self): print('爬树') class Monkey_Sun(God,Monkey): #悟空 pass sun = Monkey_Sun print(Monkey_Sun.mro()) #mor查看多继承继承顺序!
-
super 多继承
-
#super(S,self) 严格按照,self从属于类的mro的执行顺序,执行类的下一位 #示例1: class A: def f1(self): print("in A") class Foo(A): def f1(self): super(Foo,self).f1() #FOO下一个类Bar print("in Foo") class Bar(A): def f1(self): print("in Bar") class Info(Foo,Bar): def f1(self): super(Info,self).f1() #Info属于第一个类,每次找下一个类,下个是Foo print("in info f1") obj = Info() obj.f1() #示例2: class A: def f1(self): print("in A") class Foo(A): def f1(self): super(Foo,self).f1() print("in Foo") class Bar(A): def f1(self): print("in Bar") class Info(Foo,Bar): def f1(self): super(Foo,self).f1() print("in info f1") obj = Info() obj.f1()
-
MRO算法,C3算法:
-
class O: pass class D(O): pass class E(O): pass class F(O): pass class B(D,E): pass class C(E,F): pass class A(B,C): pass #取第一个表头匹配表尾,不相同取出,如果相同,匹配下一个列表的表头 #例子[C,E,F,O] = 表头[C] 表尾[E,F,O] #只能拿表头匹配 """ mro(A) = mro(A(B,C)) 原式 = [A] + merge(mro(B),mro(C),[B,C]) mro(B) = mro(B(D,E)) = [B] + merge(mro(D),mro(E),[D,E]) #多继承 = [B] + merge([D,O],[E,O],[D,E]) #单继承,O都是单继承 = [B,D] + merge([O],[E,O],[E]) #取出D之后,删除D = [B,D,E,O] mro(C) = mro(C(E,F)) = [C] + merge(mro(E),mro(F),[E,F]) = [C] + merge([E,O]),[F,O],[E,F]) = [C,E] + merge([O]),[F,O],[F]) = [C,E,F,O] mro(A) = mro(A(B,C)) 原式 = [A] + merge([B,D,E,O],[C,E,F,O],[B,C]) = [A,B] + merge([D,E,O],[C,E,F,O],[C]) = [A,B,D] + merge([E,O],[C,E,F,O],[C]) = [A,B,D,C] + merge([E,O],[E,F,O]) = [A,B,D,C,E] + merge([O],[F,O]) = [A,B,D,C,E,F,O] """
-
封装:
-
将一些 数据属性和方法封装起来,还可以取出来,就是封装
-
将你的数据放到列表里面也是封装,这是数据层面的
-
常用的代码段放到函数里面,这是语句层面封装
-
而类是一种更高级的封装,他可以将这两种封装在一起
-
广义:
- 把属性和方法装起来,外面不能直接调用了,要通过类的名字来调用
-
狭义:
- 把属性和方法藏起来,外面不能调用,只能在类的内部调用
多态:
-
python:默认支持多态
- 同一个对象,多种形态,A=1 A=“ad”
- 一个类表现出多种形态,当你定义一个苹果支付类和微信支付类,他们同属于支付类,可以在支付类中定义双下方法属性
-
鸭子类型:
- python中 你看起来像鸭子,你就是鸭子
- A,B两个类,没有任何关系,独立两个,但是里面的功能相似,所以python一般会将类似于A,B两个类里面的相似功能让其命名相同
- A,B虽然无关系,但是很默契的制定了一个规范,让你使用更方便
类的约束:
- 类的约束是一个开发规范,约束他的所有子类必须实现和他同名的方法,不同名抛出错误
- 作用:
- 在重要的逻辑,与用户数据相关等核心部分,我们要进行约束,避免此类错误
-
第一种约束(常用):主动抛异常
-
#在父类中定义个pay方法,主动抛出异常,如果子类中没有定义pay方法,会寻找父类 #即会报错,python推荐的一种约束方式 class Payment: #主动报错 def pay(self,money): #约定俗称,定义一种规范,子类要定义pay方法 raise Exception('子类必须定义此方法') class Alipay(Payment): def pay(self,money): print(f"利用支付宝支付了{money}") class Wechatpay(Payment): def fuqian(self,money): print(f"利用微信支付了{money}") #支付 def pay(obj,money): obj.pay(money) obj1 = Alipay() #调用支付宝支付 pay(obj1,100) obj2 = Wechatpay() #调用微信支付 pay(obj2,200)
-
第二种约束:实例化对象时报错,严谨
-
#利用抽象类的概念:基类如上设置,子类如果没有定义pay方法,在实例化对象时报错 from abc import ABCMeta,abstractclassmethod class Payment(metaclass=ABCMeta): #约束子类必须要有pay方法 @abstractclassmethod def pay(self,money): pass class Alipay(Payment): def pay(self,money): print(f"利用支付宝支付了{money}") class Wechatpay(Payment): def fuqian(self,money): print(f"利用微信支付了{money}") #支付 def pay(obj,money): obj.pay(money) obj1 = Alipay() obj2 = Wechatpay() #调用微信 pay(obj1,100) pay(obj2,200)
反射:
-
通过字符串形式,反射类中的属性和方法
-
反射的四个函数:
-
hasattr(obj,"字符串") #判断字符串是否存在类中 getattr(obj,"字符串") #进行反射调用字符串(属性或者方法) setattr(obj,"字符串") #添加属性 delattr(obj,"字符串") #删除属性
-
实例角度反射:
-
class A: static_field = "静态属性" def __init__(self,name,age): self.name = name self.age = age def func(self): print("in A func") obj = A("海洋",18) if hasattr(obj,"static_field"): #判断boj对象是否有static_field print(getattr(obj,"static_field")) if hasattr(obj,"func"): #判断hasttr是否有函数 getattr(obj,"func")() #执行对象内的方法 # print(getattr(obj,"name",None)) #没有属性,可以自定义设置返回值 # setattr(obj,"hobby",'台球') #* 添加一个属性 # print(getattr(obj,"hobby")) # # delattr(obj,"hobby") #* 删除一个属性 # print(getattr(obj,"hobby"))
-
类的角度反射:
-
class A: static_field = "静态属性" def __init__(self,name,age): self.name = name self.age = age def func(self): print(self) print(self.name) print("in A func") # print(hasattr(A,"static_field")) # print(getattr(A,"static_field")) obj = A("海洋",18) getattr(A,"func")(obj)
-
脚本角度:
-
def func1(): print("in func1") def func2(): print("in func2") def func3(): print("in func3") class B: static = "B类" import sys this_moudles = sys.modules[__name__] #将__name__加入modules,获取当前脚本对象 getattr(this_moudles,"func1")() #调用函数 cls = getattr(this_moudles,"B") #获取到B,在进行实例化,调用 obj = cls() print(obj.static)
-
类的反射:
-
import sys class Auth: function_list = [("login","请登录"), ("register","请注册"),("exit","退出")] def login(self): print("登录函数") def register(self): print("注册函数") def exit(self): print("退出函数") while 1: obj = Auth() for num,option in enumerate(obj.function_list,1): print(num,option[1]) func_name = int(input("请输入选择:").strip()) if hasattr(obj,obj.function_list[func_name-1][0]): getattr(obj,obj.function_list[func_name-1][0])()
单例模式:
-
一个类只能实例化一个对象,无论你实例化多少次,内存中都只有一个对象,节省内存
-
主要是实例化对象,执行类中的方法
-
#单例模式:(面试必考) #一个类只能实例化一个对象,无论你实例化多少次,内存中都只有一个对象,节省内存 #这个类的对象不是个性化的,主要是实例化对象之后去执行类中的方法 class A: __instance = None def __new__(cls, *args, **kwargs): if not cls.__instance: #如果为反的话 obj1 = object.__new__(cls) #调用object __new__方法封装类名 cls.__instance = obj1 #object1对象 return obj1 else: return cls.__instance obj = A() obj1 = A() print(obj,obj1) #传参示例: class Baby: __instance = None def __new__(cls, *args, **kwargs): if cls.__instance is None: cls.__instance = object.__new__(cls) #object=super,找父类__new__ object类中的new可以创建空间 Baby = cls return cls.__instance def __init__(self,cloth,pants): #self = b1 self.cloth = cloth self.pants = pants b1 = Baby('黑衣服','黑裤子') b2 = Baby('白衣服','白裤子') print(b1.__dict__) print(b2.__dict__)
类的成员:
-
方法:
-
__ 将属性和方法变成私有
-
@classmethod : 调用类名
-
@staticmethod: 变成普通函数
-
@property : 将方法变成属性
-
私有:
- 私有静态属性,私有对象方法属性:
- 类的外部都不可调用,只能在类中调用,适用于安全加密方式可以设置成私有(假私有)
-
#公有静态属性: class B: school_name = "海洋" __haha = "haha" class A(B): class_name = "python" __junli = "1" #私有静态属性:外部不可访问 def func(self): print(self.__junli) #只能在类的内部可以访问 print(self.__haha) obj = A() print(obj.func()) #私有对象属性: class B: def __init__(self,weight): self.__weight = weight class A(B): def __init__(self,name,age,weight): super().__init__(weight) #super要放在最上面 self.name = name self.__age = age def func(self): print(self.__age) #类的外部不能访问,只可以内部调用 print(self.__weight) #私有属性,父类中也不可调用 obj = A("海洋",18,120) print(obj.func()) #python中的所有私有成员:就是在私有成员前面加上_类名而已 #不建议这样去访问 class A: __junli = "1" print(A._A__junli)
@classmethod:调用类名
-
#定义一个学生类,统计学生个数 class Student: sum = 0 def __init__(self,name): self.name = name self.count() @classmethod #类方法:由类名直接调用的方法,他会自动将类名传给cls def count(cls): cls.sum = cls.sum + 1 #使用类名是可以修改静态方法中的sum @classmethod def get_num(cls): return cls.sum haiyang = Student("海洋") junli = Student("俊丽") print(Student.get_num()) #类名调用
@staticmethod:变成普通函数
-
#静态方法:不依赖类,也不依赖于对象,他就是一个普通的函数 #他就是一个普通的函数放置于类中结构更加清晰与合理 class A: def func(self): print(111) @classmethod def a_func(cls): #接受的是类名 print(cls) @staticmethod def static_func(a): #普通函数 print(f"静态方法{a}") A.static_func(222) #调用函数 obj = A() #实例化调用也可以 obj.static_func(222)
@property :将方法变成属性
-
#测试人体体脂 #我们要让bmi方法,伪装成属性,虽然在代码级别没有什么提升,但是看起来更合理 class Bmi: def __init__(self,name,weight,height): self.name = name self.weight = weight self.height = height @property #将方法转为属性 def bmi(self): return self.weight / self.height**2 tb = Bmi("海洋",120,1.80) print(tb.bmi) #调用属性 #@property 方法变成属性,修改和删除不常用 class Foo: def __init__(self,name): self.name = name @property def aaa(self): #设置属性是名称要唯一,setter和deleter不能return print('get时候执行我') @aaa.setter def aaa(self,v): print(f"修改的时候执行我{v}") @aaa.deleter def aaa(self): print("删除时候执行我") obj = Foo("海洋") obj.aaa = "俊丽" #调用被@aaa.setter装饰的函数,并且将"俊丽"传给v del obj.aaa #删除 print(obj.aaa) #原属性aaa没有被修改
isinstance:判断对象与类的关系
-
class A: pass class B(A): pass class C(B): pass obj = B() print(isinstance(obj,B)) #前面是对象,判断OBJ是否是是由B类(B的派生类)实例化的对象 print(isinstance(obj,A)) # print(isinstance(obj,C)) #
issubclass:
-
class A: #父类,也叫基类 pass class B(A): pass class C(B): pass print(issubclass(C,B)) #判断C是否是B的子类,子类也叫派生类 print(issubclass(C,A))
Iterable:判断类可迭代和元类
-
from collections import Iterable #判断是否可迭代 from collections import Iterator #判断迭代器 s1 = "sadaada" #class str(Iterable): # l1 = [1,2,3] # print(type(s1)) #判断对象从属于哪个类,一切皆对象 # print(type(l1)) print(isinstance(s1,Iterable)) #判断是否是可迭代对象,从继承角度 #type 元类 python中一切皆对象,一个类也是一个对象 #那么一个类肯定是由类实例化出来的 #python中你创建的所有类,以及大部分str list等等,这些类都是从type元类实例化得来的 # python中继承object都是新式类: # object也是有type元类实例化得来的 #而type类还是object子类,这种关系比较神奇无法使用python代码表述
types:
-
#函数与方法区别 #函数:全都是显性传参 #方法:存在隐性传参 #java里面就是有方法,c++中都是函数 from types import FunctionType #判断函数 from types import MethodType #判断方法 def func(): pass class A: def func(self): pass @staticmethod def f(self): pass print(isinstance(func,FunctionType)) #判断是否是函数 print(isinstance(func,MethodType)) print(isinstance(A.func,FunctionType)) #类名调用func 是一个函数 print(isinstance(A.func,MethodType)) obj = A() print(isinstance(obj.func,FunctionType)) print(isinstance(obj.func,MethodType)) #通过对象调用是方法 obj = A() print(isinstance(obj.f,FunctionType)) #通过对象调用静态方法是函数 print(isinstance(obj.f,MethodType))
双下方法:
-
双下方法触发条件:
-
__new__: 在实例化时候触发,触发优先级比__init__高,单例模式使用 __len__: len(obj) len对象时候触发 __str__: str(obj)或者格式化输入时候触发 __call__: 实例化对象后触发,call优先级比__init__方法低
-
-
__new__
方法: -
#开辟一个空间 class A: def __init__(self): print("in init") def __new__(cls, *args, **kwargs): #cls = A类名 print("in new") object1 = object.__new__(cls) #2.利用object类的new产生一个空间 return object1 #3.将这个对象空间返回给A() obj = A() #1.先触发__new__并且将类名自动传给cls
-
__len__
方法: -
#一个对象值所以可以使用len函数,是这个对象从属于类中有__len__方法 class A: def __init__(self,name,age,hobby): self.name = name self.age = age self.hobby = hobby def __len__(self): print("执行了__len__方法") return len(self.__dict__) obj = A("海洋",18,"台球") ret = len(obj) #触发A类中的__len__方法,ret返回10 print(ret)
-
__str__
方法: -
class Student: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def __str__(self): return f"{self.name}{self.age}{self.sex}" #str优先级高 # def __repr__(self): #跟str双下方法一样 # return f"{self.name}{self.age}{self.sex}" obj = Student("海洋",18,"男") obj1 = Student("俊丽",18,"女") # # print(str(obj)) #会触发 # print(obj) #打印一个实例就会触发__str__ # print(obj1) print(f"此对象为{obj}") #格式化输出也会触发
-
__call__
方法: -
# 对象call ,类加()触发 class A: def __init__(self): self.a = 1 print(111) def __call__(self, *args, **kwargs): print(222) obj = A() #实例化触发 obj()
-
__enter__和__exit__方法:
-
#对一个对象类似于进行with语句上下文管理,必须要在类当中定义__enter__和__exit__ class A: def __init__(self,text): self.text = text def __enter__(self): self.text = self.text + "您来了" #1 return self def __exit__(self, exc_type, exc_val, exc_tb): self.text = self.text + "这就走了" # with A("大爷") as f1: #2 print(f1.text) print(f1.text) #4
-
#__eq__ 对象比较是触发 #__del__ 析构方法,手动垃圾挥手 #__item__ 对一个对象,执行字典的操作,执行item #__iter__ 将一个对象设置成一个可迭代对象,for循环取值或者list
异常处理:
-
一旦程序出现异常,异常处理会及时捕捉你的错误,不至于使你的程序崩溃
-
异常处理不能经常使用:耗费性能,有些错误是需要分流使用的,代码的可读性变差
-
关键的节点时候使用
-
单分支:
-
try: l1 = [1,2,3,4,5] print(l1[6]) except IndexError as e: #当索引报错后,后面的就不会再走了 print("索引错误") print(111)
-
多分支和分流:
-
try: l1 = [1,2,3,4,5] print(l1[6]) dic = {1:2,'a':'b'} print(dic[3]) num = input("请输入序号:") int(num) except IndexError as e: #当索引报错后,后面的就不会再走了 print("索引错误") except KeyError as e: print('没有此键') except ValueError as e: print("转化错误") print(111) #程序分流 dic = { 1:666, 2:333, 3:555 } while 1: try: num = input("请输入序号:") int(num) print(dic[int(num)]) except KeyError as e: print(f'选项超出范围,请重新输入{e}') #e是将错误打印出来 except ValueError as e: print(f"请输入数字{e}")
-
万能异常:
-
# 万能异常 # 什么时候使用万能异常,什么时候使用多分支? # 如果你只是想把整个异常全部处理掉,让程序继续执行,就用万能异常 # 如果出现了异常,你是想根据不同的异常执行不同的逻辑流程,你要采取多分支 dic = { 1:666, 2:333, 3:555 } try: num = input("请输入序号:") int(num) print(dic[int(num)]) except Exception as e: #代表所有错误,全部捕获 print(e) print(111)
-
万能异常加分流:
-
dic = { 1:666, 2:333, 3:555 } while 1: try: num = input("请输入序号:") int(num) print(dic[int(num)]) except KeyError as e: print('选项超出范围,请重新输入') except ValueError as e: print("请输入数字") except Exception: #以上异常没有pass掉 pass
-
异常处理其他成员:无异常时候执行
-
dic = { 1:666, 2:333, 3:555 } try: num = input("请输入序号:") int(num) print(dic[int(num)]) except KeyError as e: print("选项超出范围,重新输入") except Exception: pass else: #以上无异常执行else语句,否则不执行else语句 print(666)
-
finally:在出现错误前执行此语句
-
#使用场景,文件读写,数据库连接 try: int("a") finally: #finally: 在出错误前执行此语句 print(777) def func(): #函数结束前执行finally try: a = 1 b = 2 return a + b finally: print(666) print(func())
-
raise/assert:主动抛出异常
-
raise Exception("主动抛出异常") assert #断言:可以添加条件加判断 assert 1 == 2 print(11)
-
自定义异常(了解)
-
class Connection(BaseException): def __init__(self,msg): self.msg=msg raise Connection("触发了连接异常")