注意:
当一个函数的返回值是一个布尔值的时候,如果把这个函数做为条件放到 if 或者while后面的时候,后面不用再写==True,也就是说:此时的 if 函数名 等价于 if 函数名 ==True ,如果函数返回True,则原式就等于if True,代表条件成立,就会执行if条件下面的代码。反之,如果函数返回的是False,就代表条件不成立,就不会执行if下面的代码。但是,如果一个函数返回False,才执行if语句的话,可以写成:if not 函数名。
一、异常
程序错误分两种情况:
(1)语法错误。写出来的代码不符合python的语法规则。
(2)异常。代码本身没有错误,但是在运行的时候却报错了,这就叫异常。
例如:语法错误举例。
num = aasint(input("请输入一个整数:")) # aasint 不是python里面的函数
print( # 后面少了半个括号
例如:异常的举例。
num = int(input("请输入一个整数:")) # 这就叫代码本身没有错误
print("hello word")
# 执行,输入abc结果报错,这就是异常
请输入一个整数:abc
Traceback (most recent call last):
File "D:/study_python/yy_daima/yichang/", line 1, in <module>
num = int(input("请输入一个整数:"))
ValueError: invalid literal for int() with base 10: 'abc'
进程已结束,退出代码 1
从上面代码中可以看到,当代码一旦遇到错误,程序就会停止运行,剩下的代码也就不会再执行了,就比如print("hello word")这行就没执行。
程序停止运行,并且抛出错误信息的这个动作,叫做抛出异常。
为了更好的保证程序的健壮性和稳定性,通常都会在代码中加入捕获异常的机制。
二、捕获异常
在程序开发过程中,如果有些代码的执行不确定是否正确,可以给它加个try....except来捕获异常。
语法格式:
try:
可能出现异常的代码
except:
出现异常后要执行的代码
一旦try里面的代码发生异常,程序就会自动执行except里面的代码,此时,程序就不会再因为报错而终止了;如果没有发生异常,那么except里面的代码也就不会被执行。
例如:
try:
num = int(input("请输入一个整数:"))
except:
print("输入的不对!")
结果:
请输入一个整数:2 # 没有发生异常,不会执行except
进程已结束,退出代码 0
请输入一个整数:a # 错误输入,出现异常,执行except
输入的不对!
进程已结束,退出代码 0
三、捕获不同类型的异常
在程序执行的过程中,可能会遇到各种各样的报错信息,为了提高代码的友好度,可以根据不同的报错信息,做出不同的响应。就好比,我错了,那我具体哪错了。
语法格式:
try:
可能出现异常的代码
except 异常类型1:
出现异常后要执行的代码
except 异常类型2:
出现异常后要执行的代码
......
例如:由用户输入两个整数,然后输出这两个数相除后的结果。
try:
num1 = int(input("请输入num1:"))
num2 = int(input("请输入num2:"))
print(num1 / num2)
except ValueError:
print("请输入纯数字!")
except ZeroDivisionError:
print("除数不能为0!")
结果:
请输入num1:1
请输入num2:2
0.5
进程已结束,退出代码 0
请输入num1:f
请输入纯数字!
进程已结束,退出代码 0
请输入num1:1
请输入num2:d
请输入纯数字!
进程已结束,退出代码 0
请输入num1:5
请输入num2:0
除数不能为0!
进程已结束,退出代码 0
例如:对一个能够进行加减乘除运算的计算器,进行异常捕获。
try:
num1 = int(input("请输入第一个数"))
num2 = int(input("请输入第二个数"))
opt = input("请输入+、-、*、/中的任意一个字符:")
if opt == "+":
print(num1 + num2)
elif opt == "-":
print(num1 - num2)
elif opt == "*":
print(num1 * num2)
elif opt == "/":
print(num1 / num2)
else:
print("输入的运算符不正确")
except ValueError:
print("请输入纯数字")
except ZeroDivisionError:
print("除数不能为0!")
结果:
请输入第一个数1
请输入第二个数2
请输入+、-、*、/中的任意一个字符:/
0.5
请输入第一个数a
请输入纯数字
请输入第一个数2
请输入第二个数0
请输入+、-、*、/中的任意一个字符:/
除数不能为0!
四、捕获未知错误——except Exception as result
通过故意输入错误的数据,可以看到程序的报错类型,但有些错误不一定能很快就试验出来,所以,对于这些未知的错误,可以用except Exception as result进行捕获。
语法格式:
try:
可能出现异常的代码
except Exception as result: #result是个变量名,可以随便起,一般习惯写result
print(result) # 出现未知异常时执行的代码
# print(result)就是把捕获的这个异常提示信息给打印出来。
# 也就是说,让我能看到这里为啥报错了。
但是一般用的不多,因为,在编写代码时候基本就会把可能报错的类型都考虑进入了,如果没考虑进去,用这种方式得到的错误信息也不一定能看的懂。
例如:让一个字符串和一个整数用加号进行拼接,使用except Exception as result来捕获异常。
try:
a = "23" # 字符串
b = 1 # 整型
print(a + b) # 这俩不能进行拼接
except Exception as result:
print(result)
结果:
can only concatenate str (not "int") to str
进程已结束,退出代码 0
五、没有发生异常时才执行的代码——else
如果程序在运行过程中,没有发生异常,还需要额外再执行一些代码,就可以用else。也就是说,只有try里面的代码不发生异常,才会执行else里面的代码
格式:
try:
可能出现异常的代码
except Exception as result: # 或者这里按异常类型来写
发生异常时要执行的代码
else:
没有发生异常时要执行的代码
例如:由用户输入两个整数,然后输出这两个数相除后的结果。
try:
num1 = int(input("请输入num1:"))
num2 = int(input("请输入num2:"))
print(num1 / num2)
except ValueError:
print("请输入纯数字的字符串")
except ZeroDivisionError:
print("除数不能为0!")
else:
print("代码没有发生异常")
结果:
请输入num1:1
请输入num2:2
0.5
代码没有发生异常 # 也就是说,只有try里面的代码不发生异常,才会执行else里面的代码
请输入num1:1
请输入num2:0
除数不能为0!
六、不管有没有发生异常,都要执行的代码——finally
语法:
try:
可能出现异常的代码
except Exception as result: # 或者这里按异常类型来写
发生异常时要执行的代码
finally:
不管有没有发生异常,都要执行的代码
例如:把上面的else改成finally.
try:
num1 = int(input("请输入num1:"))
num2 = int(input("请输入num2:"))
print(num1 / num2)
except ValueError:
print("请输入纯数字的字符串")
except ZeroDivisionError:
print("除数不能为0!")
finally:
print("不管有没有发生异常,我都要执行")
结果:
请输入num1:1
请输入num2:2
0.5
不管有没有发生异常,我都要执行
请输入num1:a
请输入纯数字的字符串
不管有没有发生异常,我都要执行
七、综合
把上面的所有语法写在一起。
try:
可能出现异常的代码
except 异常类型1:
出现异常后要执行的代码
except 异常类型2:
出现异常后要执行的代码
except Exception as result:
出现未知异常时要执行的代码
else:
没有发生异常时才执行的代码
finally:
不管有没有发生异常, 都要执行的代码
例如:
try:
num1 = int(input("请输入num1:"))
num2 = int(input("请输入num2:"))
print(num1 / num2)
except ValueError:
print("请输入纯数字的字符串")
except ZeroDivisionError:
print("除数不能为0!")
except Exception as result: # 捕获未知错误
print("未知错误:", result)
else:
print("代码没有发生异常") # else发生异常就不执行
finally:
print("代码执行完毕") # 不管有没有发生异常,都会执行
结果:
请输入num1:1
请输入num2:2
0.5
代码没有发生异常
代码执行完毕
请输入num1:a
请输入纯数字的字符串
代码执行完毕
八、人为的主动抛出异常
抛出异常使用关键字raise,python中还提供了一个Exception异常类。
格式:
raise Exception("对异常的描述")
例如:用户设置密码,如果密码长度小于6,则抛出异常。
str1 = input("请输入密码:")
if len(str1) < 6:
raise Exception("密码至少要设置为6位数!")
else:
print("密码设置成功!")
print("代码执行结束")
结果:
请输入密码:123ab
Traceback (most recent call last):
File "D:/study_python/yy_daima/yichang/", line 121, in <module>
raise Exception("密码至少要设置为6位数!")
Exception: 密码至少要设置为6位数!
请输入密码:aabbcc
密码设置成功!
代码执行结束
解析:第一次输入时,输入的是5个字符,所以if条件成立,就会抛出异常,而后面的print("代码执行结束")这行代码也不执行了。说明,主动抛出的异常同样也会导致程序的终止。所以,无论是系统自动抛出的异常还是人为主动抛出的异常,都需要进行捕获,才能让程序继续往下运行。
即:只要是异常,都要进行捕捉,否则代码报错程序执行中断。
优化上面的代码:加入捕获异常的机制。
try:
str1 = input("请输入密码:")
if len(str1) < 6:
raise Exception("密码至少要设置为6位数!")
else:
print("密码设置成功!")
except Exception as result: # 加入这两行代码
print(result)
print("代码执行结束")
结果:
请输入密码:abc
密码至少要设置为6位数!
代码执行结束
请输入密码:123456
密码设置成功!
代码执行结束
这样代码就会更加友好,无论有没有发生异常,最后一行代码print("代码执行结束")都能执行了。
例如:主动抛出异常举例。
定义两个变量:name、age,分别通过input函数进行输入。
要求:当name中有数字字符时,或者,age小于等于0时,都抛出异常,并进行捕捉。
法1:
try:
name = input("请输入姓名:")
for i in name:
if i >= "0" and i <= "9":
raise Exception("名字输的不对,名字中不能有数字!")
age = int(input("请输入年龄:"))
if age <= 0:
raise Exception("年龄输的不对,年龄必须大于0!")
except Exception as result:
print(result)
结果:
请输入姓名:123
名字输的不对,名字中不能有数字!
请输入姓名:a
请输入年龄:-10
年龄输的不对,年龄必须大于0!
# 正确的输入
请输入姓名:a
请输入年龄:8
进程已结束,退出代码 0
法2:可以把判断名字有没有数字,这个拿出来写到外面,封装成一个函数。
def digital(str1): # 定义一个函数,专门用来判断名字里有没有数字
for i in str1:
if i >= "0" and i <= "9":
return True # 如果有数字,返回True
return False # 如果没有数字,返回False
try:
name = input("请输入姓名:")
if digital(name): # 调用函数,把name作为实参传进去
raise Exception("名字输的不对,名字中不能有数字!")
age = int(input("请输入年龄:"))
if age <= 0:
raise Exception("年龄输的不对,年龄必须大于0!")
except Exception as a:
print(a)
结果:
请输入姓名:123 # 当输入第一个的时候出现错误,立马捕获
名字输的不对,名字中不能有数字!
请输入姓名:abc
请输入年龄:-10
年龄输的不对,年龄必须大于0!
注意踩坑!!!
上面的代码中,都是把name和age的输入函数分开来写的,所以,只要把哪个写错了就会立马报错,这样代码比较智能。然而下面的代码就不那么智能了,存在一个问题,如果把姓名跟年龄的输入都一起写到最上面,那么当俩都出现错误时,只会捕捉到第一个异常。例如下面的第一个输入中,名字跟年龄都输错了,但最终却只捕获到了一个,显然这种是不友好的。
try:
name = input("请输入姓名:")
age = int(input("请输入年龄:"))
for i in name:
if i >= "0" and i <= "9":
raise Exception("名字输的不对,名字中不能有数字!")
if age <= 0:
raise Exception("年龄输的不对,年龄必须大于0!")
except Exception as result:
print(result)
结果:
请输入姓名:123
请输入年龄:-10
名字输的不对,名字中不能有数字! # 名字、年龄都错了,但只捕获到了一个异常
请输入姓名:1
请输入年龄:8
名字输的不对,名字中不能有数字! # 名字错,年龄对
注意:
当一个函数的返回值是一个布尔值的时候,如果把这个函数做为条件放到 if 或者while后面的时候,后面不用再写==True,也就是说:此时的 if 函数名 等价于 if 函数名 ==True ,如果函数返回True,则原式就等于if True,代表条件成立,就会执行if条件下面的代码。反之,如果函数返回的是False,就代表条件不成立,就不会执行if下面的代码。但是,如果一个函数返回False,才执行if语句的话,可以写成:if not 函数名。