一、异常处理
1. 什么是异常处理 异常是错误发生的信号,一旦程序出错就会产生一个异常,如果该异常 没有被应用程序处理,那么该异常就会抛出来,程序的执行也随之终止
异常包含三个部分: 1. traceback异常的追踪信息 2. 异常的类型 3. 异常的信息
错误分为两大类: 1. 语法上的错误:在程序运行前就应该立即修正 2. 逻辑上的错误
2. 为何要异常处理
避免程序因为异常而崩溃,所以在应用程序中应该对异常进行处理,从而增强程序的健壮性
3. 如何异常处理
try: 代码1 代码2 代码3 ...... except NameError: 当抛出的异常是NameError时执行的子代码块 except ....: pass except ...: pass else: pass finally: pass
3.1常见的逻辑错误导致的异常
print('adsfsadf' age=input('>>: ').strip() print(age > 10) #TypeError for i in 10: #TypeError pass import os os.xxx #AttributeError 1 / 0 #ZeroDivisionError: print('=====1') print('=====2') print('=====3') l=[1,2,3]# l[1000] #IndexError print('=====4') d={'x':1,'y':2} d['z'] #KeyError print('=====5')
3.2异常处理
3.2.1异常处理的单分支
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')
3.2.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 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: print(e) print('other code')
3.2.3万能异常类型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') try... else... 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) else: print('else必须放到后面,else的子代码块会在被检测的代码没有异常的情况下执行') # print('other code') try... finally... try: f=open('a.txt','w') print('=====1') print('=====2') print('=====3') d = {'x': 1, 'y': 2} # d['z'] # KeyError # xxx 'xx' > 10 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) else: print('else必须放到后面,else的子代码块会在被检测的代码没有异常的情况下执行') finally: print('无论被检测的代码有没有异常都会执行') f.close()
4几个异常的用法
4.1主动触发异常
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('name必须是字符串类型str') if not isinstance(age,int): raise TypeError('age必须是整型int') self.__name=name self.__age=age obj=People('liu',18) obj.set_info('egon',2.0) obj.tell_info()
4.2自定义异常(了解)
class Mymeta(BaseException): def __init__(self,name): self.name=name def __str__(self): return '%s'%self.name raise Mymeta('LIU')
4.3断言(了解)
print('上半部分,生产数据') l=[1,2,3] # if len(l)!=5: # raise TypeError assert len(l)==5 print('下半部分,处理数据')
二、元类的介绍
1、什么是元类?
源自一句话:在Python中一切皆为对象,二对象都是由类实例化得到的
class OldboyTeacher: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def score(self): print('%s is scoring' %self.name) tea1=OldboyTeacher('egon',18,'male') print(type(tea1)) print(type(OldboyTeacher))
对象tea1是调用OldboyTeacher类得到的,如果说一切皆对象,
那么OldboyTeacher也是一个对象,只要是对象 都是调用一个类实例化得到的,即OldboyTeacher=元类(...),内置的元类是type
关系: 1. 调用元类---->自定义的类
2. 调用自定义的类---->自定义的对象
class关键字创建自定义类的底层的工作原理,分为四步
1. 先拿到类名:'OldboyTeacher'
2. 再拿到类的基类们:(object,)
3. 然后拿到类的名称空间???(执行类体代码,将产生的名字放到类的名称空间也就是一个字典里,补充exec)
4. 调用元类实例化得到自定义的类: OldboyTeacher=type('OldboyTeacher',(object,),{...})
class OldboyTeacher: #OldboyTeacher=type(...) school = 'Oldboy' def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def score(self): print('%s is scoring' %self.name) print(OldboyTeacher)
注意:
自定义类的三个关键组成部分:
1. 类名
2. 类的基类们
3. 类的名称空间
不依赖class关键字创建一个自定义类 # 1. 拿到类名 class_name='OldboyTeacher' #2. 拿到类的基类们:(object,) class_bases=(object,) #3. 拿到类的名称空间 class_dic={} class_body=""" """ exec(class_body,{},class_dic) print(class_dic) #4. 调用type得到自定义的类 OldboyTeacher=type(class_name,class_bases,class_dic) print(OldboyTeacher) # print(OldboyTeacher.school) # print(OldboyTeacher.score) tea1=OldboyTeacher('egon',18,'male') print(tea1.__dict__)
3、自定义元类来控制自定义类的产生于调用过程
# 模板 # class Mymeta(type): #但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类 # def __init__(self,class_name,class_bases,class_dic): # print(self) # print(class_name) # print(class_bases) # print(class_dic) # # class OldboyTeacher(object,metaclass=Mymeta): #OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...}) # school = 'Oldboy' # # def __init__(self,name,age,sex): # self.name=name # self.age=age # self.sex=sex # # def score(self): # print('%s is scoring' %self.name) # 控类的产生 # 1.类名必须用驼峰体 # 2.类体必须有文档注释,且文档注释不能为空 class Mymeta(type): #但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类 def __init__(self,class_name,class_bases,class_dic): if class_name.islower(): raise TypeError('类名必须使用驼峰体') doc=class_dic.get('__doc__') if doc is None or len(doc) == 0 or len(doc.strip(' ')) == 0: raise TypeError('类体中必须有文档注释,且文档注释不能为空') class OldboyTeacher(object,metaclass=Mymeta): #OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...}) school = 'Oldboy' def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def score(self): print('%s is scoring' %self.name) print(OldboyTeacher.__dict__)
补充:属性查找
class Mymeta(type): # 但凡继承了type的类才能称之为自定义的元类,否则就是只是一个普通的类 # n=444 def __call__(self, *args, **kwargs): #self=OldboyTeacher这个类 # 1. 先产生一个空对象 tea_obj = self.__new__(self) # tea_obj是OldboyTeacher这个类的对象 # print(self.__new__ is object.__new__) # tea_obj=object.__new__(self) # 2. 执行__init__方法,完成对象的初始属性操作 self.__init__(tea_obj, *args, **kwargs) # 3. 返回初始化好的那个对象 return tea_obj class Bar: # n = 33 pass class Foo(Bar): # n = 222 pass class OldboyTeacher(Foo, metaclass=Mymeta): # OldboyTeacher=Mymeta('OldboyTeacher',(object,),{...}) # n = 111 school = 'Oldboy' def __init__(self, name, age, sex): self.name = name #None.name='egon' self.age = age self.sex = sex def score(self): print('%s is scoring' % self.name) def __new__(cls, *args, **kwargs): # print('=====>') return super().__new__(cls) tea1 = OldboyTeacher('egon', 18, 'male') # print(tea1) print(tea1.__dict__) # print(OldboyTeacher.n) # print(object.__new__)