14-面向对象3
__new__方法
__new__和__init__方法的作用
11 class A(object): 12 def __init__(self): 13 print("这是__init__方法") 14 15 def __new__(cls): 16 print('这是__new__方法') 17 return object.__new__(cls) 18 19 A()
运行结果如下:
这是__new__方法 这是__init__方法
总结:
- __new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由python解释器自动提供
- __new__方法必须要有返回值,返回实例化出来的实例,这点在自己实现__new__要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例
- __init__有一个参数self,就是这个__new__方法返回的实例,__init__方法在__new__的基础上可以完成一些其他初始化的动作,__init__不需要返回值
- 我们可以将类比作制造商,__new__方法就是前期的原材料购买环节,__init__方法就是在有原材料的基础上,加工,初始化商品环节
异常
异常介绍
当python检测到一个错误的时候,解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的“异常”
举例说明:
print ('------test1-------') open('123.txt','r') print ('------test2-------')
运行结果如下:
------test1------- Traceback (most recent call last): File "05-异常.py", line 12, in <module> open('123.txt','r') FileNotFoundError: [Errno 2] No such file or directory: '123.txt'
说明:打开一个不存在的文件123.txt,当找不到123.txt文件时,就会抛出给我们一个FileNotFoundError类型的错误No such file or directory: '123.txt'(没有123.txt这样的文件或目录)
捕获异常try...except...
看一下示例:
11 try: 12 print('-------test1---------') 13 open('123.txt','r') 14 print('-------test2---------') 15 except FileNotFoundError: 16 print('文件没有找到')
运行结果如下:
-------test1--------- 文件没有找到
说明:
- 此程序在运行过程中抛出FileNotFoundError类型的错误,我们用了except添加了处理方法
总结:
把可能出现问题的代码放到try中
把处理异常的代码放到exvept中
except捕获多个异常
看如下示例:
11 try: 12 print(num) 13 except FileNotFoundError: 14 print('产生错误')
运行结果如下:
Traceback (most recent call last): File "07-捕获多个异常.py", line 12, in <module> print(num) NameError: name 'num' is not defined
我们都已经用except来捕获异常了,那么为什么还会产生错误呢?
因为except捕获的是FileNotFoundError异常信息,没有NameError,所以程序才会出错
修改后的代码如下:
11 try: 12 print(num) 13 except NameError: 14 print('产生错误')
运行结果如下:
产生错误
在实际开发过程中,捕获多个异常是这样的:
11 try: 12 print('-------test1---------') 13 open('123.txt','r') 14 print('-------test2---------') 15 print(num) 16 except (FileNotFoundError,NameError): 17 print(errorMsg)
运行结果为:
-------test1--------- Traceback (most recent call last): File "06-捕获异常.py", line 13, in <module> open('123.txt','r') FileNotFoundError: [Errno 2] No such file or directory: '123.txt' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "06-捕获异常.py", line 21, in <module> print(errorMsg) NameError: name 'errorMsg' is not defined
注意:
- 当捕获多个异常的时候,可以把要捕获的异常的名字,放到except后面,并使用元组的方式进行存储
获取异常的信息描述
In [1]: try: ...: print(num) ...: except NameError as result: #as result存储异常的基本信息 ...: print(result) ...: name 'num' is not defined
捕获所有异常
没有存储异常的基本信息
In [1]: try: ...: open('a.txt') ...: except: ...: print('产生了一个异常') ...: 产生了一个异常
捕获所有异常,并且存储异常的基本信息
In [2]: try: ...: open('a.txt') ...: except Exception as result: ...: print('捕获到了异常') ...: print(result) ...: 捕获到了异常 [Errno 2] No such file or directory: 'a.txt'
else
我们对else应该不陌生,在if中,它的作用是当条件不满足时执行的实行,同样在try...except中也是如此,即如果没有捕获到异常,那么就需要执行else的事情
In [4]: try: ...: num = 100 ...: print(num) ...: except NameError as result: ...: print('捕获到了异常') ...: print(result) ...: else: ...: print('没有捕获到异常,真开心') ...: 100 没有捕获到异常,真开心
try...finally...
在程序中,如果一个段代码必须要执行,即无论异常是否产生都要执行,那么此时就需要使用finally。比如关闭文件,释放锁,把数据库连接返回给连接池等
举例说明:
1 #!/usr/bin/python 2 #coding=utf8 3 """ 4 # Author: xiaoyafei 5 # Created Time : 2018-04-08 18:46:34 6 7 # File Name: 08-try_finally.py 8 # Description: 9 10 """ 11 import time 12 try: 13 f = open('test.txt') 14 try: 15 while True: 16 content = f.readline() 17 if len(content)==0: 18 break 19 time.sleep(2) 20 print(content) 21 except: 22 #如果在读取文件的过程中产生了异常,那么就会捕捉到 23 #比如,按下了ctrr+c 24 pass 25 finally: 26 f.close() 27 print('文件已正常关闭') 28 except: 29 print('没有这个文件')
然后, 需要在当前目录下touch文件test.txt,然后再运行,运行结果如下:
文件已正常关闭
说明:
- test.txt文件中每一行数据打印,但是可以在每次打印的时候暂停2秒,这样的做法就是让程序运行慢一点,在程序运行的时候,可以ctrl+c中断程序
- 当按下ctrl+c的时候,异常被触发,程序退出,但是在退出程序之间,finally从句依然被执行把文件关闭
异常的嵌套
try嵌套
1 #!/usr/bin/python 2 #coding=utf8 3 """ 4 # Author: xiaoyafei 5 # Created Time : 2018-04-08 18:46:34 6 7 # File Name: 08-try_finally.py 8 # Description: 9 10 """ 11 import time 12 try: 13 f = open('test.txt') 14 try: 15 while True: 16 content = f.readline() 17 if len(content)==0: 18 break 19 time.sleep(2) 20 print(content) 21 except: 22 #如果在读取文件的过程中产生了异常,那么就会捕捉到 23 #比如,按下了ctrr+c 24 pass 25 finally: 26 f.close() 27 print('文件已正常关闭') 28 except: 29 print('没有这个文件')
需要在当前目录下touch test.txt,然后在里面随便写点东西,运行结果如下:
aaaaaaaaaaaaaaaaaaaa ^C文件已正常关闭 #ctrl+c
函数嵌套调用中
1 #!/usr/bin/python 2 #coding=utf8 3 """ 4 # Author: xiaoyafei 5 # Created Time : 2018-04-08 19:01:45 6 7 # File Name: 09-异常的传递-函数调用中.py 8 # Description: 9 10 """ 11 def test1(): 12 print('----------test1-1---------') 13 print(num) 14 print('----------test1-2---------') 15 16 def test2(): 17 print('----------test2-1---------') 18 test1() 19 print('----------test2-2---------') 20 21 def test3(): 22 try: 23 print('----------test3-1---------') 24 test1() 25 print('----------test3-2---------') 26 except Exception as result: 27 print('捕获到了异常,信息是:%s'%result) 28 29 print('----------test3-2---------') 30 31 test3() 32 print('------------------华丽的分割线---------------') 33 test2()
运行结果如下:
----------test3-1--------- ----------test1-1--------- 捕获到了异常,信息是:name 'num' is not defined ----------test3-2--------- ------------------华丽的分割线--------------- ----------test2-1--------- ----------test1-1--------- Traceback (most recent call last): File "09-异常的传递-函数调用中.py", line 33, in <module> test2() File "09-异常的传递-函数调用中.py", line 18, in test2 test1() File "09-异常的传递-函数调用中.py", line 13, in test1 print(num) NameError: name 'num' is not defined
当调用test3函数时,在test1的函数内部产生了异常,此异常会被传递到test3函数中完成了异常处理,而当异常处理完后,并没有返回到函数test1中进行执行,而是在函数test3中继续执行
总结:
- 如果try嵌套,那么如果里面的try没有捕获到这个异常,那么外面的try会接收到这个异常,然后进行处理,如果外边的try依然没有捕获到,那么再进行传递...
- 如果一个异常实在一个函数中产生的,例如函数A-->函数B-->函数C-->,而异常是在函数 C中产生的,那么如果函数C中没有对这个异常进行处理,那么这个异常就会传递给B,如果函数B有异常处理那么则会按照函数B的处理方式进行执行;如果函数B也没有异常处理,那么这个异常会继续传递,以此类推......
抛出自定义的异常
可以用raise语句来引发一个异常。异常/错误对象必须要有一个名字,且他们应该是Error或Exception类的子类
下面是一个引发异常的例子:
1 #!/usr/bin/python 2 #coding=utf8 3 """ 4 # Author: xiaoyafei 5 # Created Time : 2018-04-08 19:14:00 6 7 # File Name: 10-抛出自定义的异常.py 8 # Description: 9 10 """ 11 class ShortInputError(Exception): 12 '''自定义的异常类''' 13 def __init__(self,length,alteast): 14 super().__init__() 15 self.length = length 16 self.alteast = alteast 17 18 def main(): 19 try: 20 s = input('请输入----->') 21 if len(s)<3: 22 #raise引发一个自定义的异常 23 raise ShortInputError(len(s),3) 24 except ShortInputError as result: 25 print('ShortInputError:输入的长度是%d,长度至少是%d'%(result.length,result.alteast)) 26 else: 27 print('没有异常') 28 main()
运行结果如下:
python@ubuntu:~/codes/python基础-09$ python3 10-抛出自定义的异常.py 请输入-----> ShortInputError:输入的长度是0,长度至少是3 python@ubuntu:~/codes/python基础-09$ python3 10-抛出自定义的异常.py 请输入----->a ShortInputError:输入的长度是1,长度至少是3 python@ubuntu:~/codes/python基础-09$ python3 10-抛出自定义的异常.py 请输入----->bd ShortInputError:输入的长度是2,长度至少是3 python@ubuntu:~/codes/python基础-09$ python3 10-抛出自定义的异常.py 请输入----->dad 没有异常
在以上代码中,关于suprt().__init__()的说明:
这一行代码,可以调用也可以不调用,建议调用,因为__init__方法 往往是用来创建完对象进行初始化工作,如果在子类中重写了父类的__init__方法,即意味着父类中的很多初始化工作没有做,这样就不能保证程序的稳定了,所以在以后的开发过程中,如果重写了父类的__init__方法,最好是先调用父类的这个方法,然后再添加自己的功能
异常处理中抛出异常
#!/usr/bin/python #coding=utf8 """ # Author: xiaoyafei # Created Time : 2018-04-08 19:25:59 # File Name: 11-异常处理中抛出异常.py # Description: """ class Test(object): def __init__(self,switch): self.switch = switch #开关 def cacl(self,a,b): try: return a/b except Exception as result: if self.switch: print('捕获开启,已经捕获到了异常,信息如下:') print(result) else: #重新抛出这个异常,此时就不会被这个异常给捕获到,从而触发默认的异常处理 raise a = Test(True) a.cacl(11,0) print('--------------------------华丽的分割线--------------------------') a.switch = False a.cacl(11,0)
运行结果如下:
捕获开启,已经捕获到了异常,信息如下: division by zero --------------------------华丽的分割线-------------------------- Traceback (most recent call last): File "11-异常处理中抛出异常.py", line 29, in <module> a.cacl(11,0) File "11-异常处理中抛出异常.py", line 16, in cacl return a/b ZeroDivisionError: division by zero