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