在Python中,程序在执行的过程中产生的错误称为异常。 如列表所以越界、打开不存在的文件等。
NameError: 尝试访问一个未声明的变量,会引发NameError。
ZeroDivisionError: 当除数为零的时候,会引发ZeroDividionError异常。
SyntaxError: 当解释器发现语法错误时,会引发SyntaxError异常。
IndexError: 当使用序列中不存在的索引时,会引发IndexError异常。
KeyError: 当使用字典中不存在的键访问值时,会引发KeyError异常。
Python处理异常的能力非常强大,它可以准确地反馈错误信息,帮助开发人员准确定位到问题发生的位置和原因。Python中使用try-except语句处理异常。其中,try语句用于检测异常,except语句用于捕获异常。
# 1. 需求:尝试打开test.txt(r) 如果文件不存在,只写方式打开w
'''
try:
可能发生错误的代码
except:
发生错误的时候执行的代码
'''
try:
f = open('test.txt','r')
except:
f = open('test.txt','w')
# 需求:尝试执行打印num,捕获异常类型NameError. 如果捕获到这个异常类型,执行打印,'有错误'
try:
print(num) # 可能发生的错误
except NameError: # 异常类型
print('有错误') # 如果捕获到该异常类型执行的代码
'''
注意:
1. 如果尝试执行的代码的异常类型和要捕获的异常类型不一致,则无法捕获异常。
2. 一般try下方只放一行尝试执行的代码
'''
# 尝试执行的代码,并不能断定它的异常类型具体是什么,在except后用元组的方式,把可能的异常类型全都书写里面
try:
print(1/0)
except (NameError, ZeroDivisionError):
print('有错误')
try:
print(1/0)
except (NameError, ZeroDivisionError) as result:
print(result) # division by zero
# 尝试执行打印num, 捕获Exception 打印异常描述信息
try:
print(num)
except Exception as result:
print(result)
# Exception是所有程序异常类的父类
# 不需要程序员指定具体的异常类型
# 捕获所有异常就是去except捕获这个Exception,从而做到捕获了父类,即捕获到了具体的某个异常类
else
'''
else表示的是如果没有异常要执行的代码
'''
try:
print(1)
except Exception as result:
print(result)
else:
print('我是else,当没有异常的时候执行的代码')
finally
# 需求:尝试以r打开文件,如果有异常以w打开这个文件,最终关闭文件
'''
finally表示的是无论是否异常都要执行的代码,例如关闭文件
'''
try:
f = open('test300.txt','r')
except Exception as e:
print(e)
f = open('test300.txt','w')
finally:
f.close()
'''
# 异常的传递指代的就是我们的异常是可以嵌套书写的,要去了解嵌套书写异常语句的时候,
我们的程序执行流程是什么.
# 这些要学习的知识点简称为异常的传递
# 如果书写打开访问模式,不写访问模式,那么默认即为只读r模式
# 先执行外层的try、except,然后在执行内层的try、except
'''
'''
需求1:尝试只读打开test.txt 文件存在读取内容,不存在提示用户
需求2:读取内容:循环读取,当无内容的时候退出循环,如果用户意外终止,提示用户已经意外终止
'''
import time
try:
f = open('test.txt')
# 尝试循环读取内容
try:
while True:
con = f.readline()
# 如果读取完成退出循环
if len(con) == 0:
break
time.sleep(3)
print(con)
except:
# 在命令提示符中如果按下ctrl+c结束符终止的键
print('程序被意外终止')
except:
print('该文件不存在')
'''
自定义异常的作用:用来我们将不满足程序逻辑的情况,进行一个反馈,报错给用户。
用来报错,报的错误不是语法错误,而是不符合我们程序逻辑要求的错误。
'''
# 1.定义异常类,继承Exception 魔法方法有init和str(设置异常描述信息)
class ShortInputError(Exception):
def __init__(self, length, min_len):
# 用户输入的密码长度
self.length = length
# 系统要求的最少长度
self.min_len = min_len
# 设置异常描述信息
def __str__(self):
return f'您输入的密码长度是{self.length},密码不能少于{self.min_len}'
def main():
# 2. 抛出异常:尝试执行:用户输入密码,如果长度小于3,抛出异常
try:
password = input('请输入密码:')
if len(password) < 3:
# 抛出异常类创建的对象
# ShortInputError(len(password),3)抛出了一个对象而已。可以理解raise相当于原来的打印。打印对象的时候,打印到的就是str魔法对象的返回值。
# raise抛出这个对象的时候,我们捕获的时候,捕获到的也是str魔法方法的返回值
raise ShortInputError(len(password),3)
# 3. 捕获该异常
except Exception as result:
print(result)
else:
print('没有异常,密码输入完成')
main()
'''
1. 异常语法
try:
可能发生的异常
except:
如果出现异常执行的代码
else:
没有异常执行的代码
finally:
无论是否异常都要执行的代码
2. 捕获异常
except 异常类型:
代码
except 异常类型 as xx:
代码
3. 自定义异常
# 1.自定义异常类
class 异常类类名(Except):
代码
# 设置抛出异常的描述信息
def __str__(str):
return ...
# 2. 抛出异常
raise 异常类名()
# 捕获异常
except Exception...
'''
# 模块就是一个python文件,直接调用这个模块里的功能,省去了自己定义功能再使用的步骤。
# 不推荐一次性导入多个模块,推荐的是跟一个模块名
# 需求:math模块下sqrt()开平方计算
# 方法一:import 模块名 模块名.功能
import math
print(math.sqrt(9)) # 3.0
# 再python当中,涉及到类似于除法计算不管参与计算的数字是否有浮点数,将来反馈回来的结果一定是浮点数。
# 方法二:from 模块名 import 功能1,功能2... 直接功能调用
from math import sqrt
print(sqrt(9))
# 方法三:from math import * 直接功能调用
from math import *
print(sqrt(9))
定义别名
# 需求:运行后暂停2秒打印hello
'''
1. 导入time模块或导入time模块的sleep功能
2. 调用功能
3. 打印hello
'''
# 1. 模块别名 注意:如果定义了别名之后就只能使用别名
# import time as tt
# tt.sleep(2)
# print('hello')
# 2. 定义别名
from time import sleep as sl
sl(2)
print('hello')
在当前文件夹中创建my_module1.py,然后在调用自己制作的模块。
my_module1.py
# 需求:一个函数,完成任意两个数字加法运算
def testA(a, b):
print(a + b)
# 测试信息
# testA(1, 1)
# print(__name__)
# 为了不频繁的删除测试信息或添加测试信息,这时可以加一个判断
# __name__是系统变量,是模块的标识符,值是:如果是自身模块值是__main__,否则是当前的模块的名字
if __name__ == '__main__':
testA(1,1)
在下面的程序里调用my_module1.py模块
'''
再python程序当中,每个模块就是一个python文件,这个python文件都有自己的名字。
name是一个系统变量,是模块的标识符,是每个python文件的标识符,如果name的使用位置再在自身模块里
那么它的值就是__main__,否则不在自身模块里面,那么这个name的值就是我们模块的名字,即是我们的python文件名。
'''
# 1. 导入模块
import my_module1
# 2. 调用功能
my_module1.testA(2,2)
'''
当导入一个模块,Python解析器对模块的搜索顺序是:
1. 当前目录
2. 如果不在当前目录,Python则搜索shell变量PYTHONPATH下的每个目录(安装解释器目录下的)
3. 如果都找不到,Python会查看默认路径。UNIX下,默认路径一般为/usr/local/lib/python(一般不涉及到默认路径)
模块搜索路径存储在system模块的sys.path变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录
注意:
自己的文件名不要和已有的模块名重复,否则导致模块功能无法使用
使用from 模块名 import 功能的时候,如果功能名字重复,调用到的是最后定义或导入的功能
'''
# 1. 自己的模块名不能和已有的模块名重复
import random
num = random.randint(1,5) # 因为在当前目录中有一个random模块,则报错
print(num)
'''
如果一个模块文件中有__all__变量,当使用from xxx import * 导入时,只能导入这个列表中的元素
'''
from my_module2 import *
testA()
# 因为testB函数没有添加all列表,只有all列表里面的功能才能导入
# testB()
下面就是my_module2.py中的代码
# 有all列表控制着导入行为,导致只导入all列表里面的功能。
# 1. 定义多个功能,把某个功能添加到__all__
__all__ = ['testA']
def testA():
print('testA')
def testB():
print('testB')
创建了一个名为mypackage的包,里面有三个文件
__init__.py
__all__ = ['my_module1']
mymodule1.py
print(1)
def info_print():
print('my_module1')
mymodule2.py
print(2)
def info_print():
print('my_module2')
这个就是导入包.py(尽量不要起中文名称),开始导包
'''
# 包将有联系的模块组织在一起,即放到同一个文件夹下,并且在这个文件夹创建一个名字为__init__.py文件,那么这个文件就称为包
# 当右键去创建包的时候,这个文件夹里面会自动创建一个名字为__init__.py的文件,这个文件可以控制包的导入行为
'''
# 方法一
'''
1. 导入
import 包名.模块名
2. 调用功能
包名.模块名.功能()
'''
# 导入mypackage包下的模块1,使用这个模块内的info_print1函数
# import mypackage.my_module1
# mypackage.my_module1.info_print()
# 方法二:注意 设置__init__.py文件里面的all列表( __all__ = [] ),添加的是允许导入的模块
'''
from 包名 import *
模块名.目标
'''
from mypackage import *
my_module1.info_print()
# 在工作岗位下,避免功能名字重复这个事情发生
# 1. 当使用from xx import 功能
# 导入模块功能的时候,如果功能名字重复,导入的时候后定义或后导入的这个同名功能
def sleep():
print('我是自定义的sleep')
from time import sleep
# 后导入的同名功能(这时就会报错)
# def sleep():
# print('我是自定义的sleep')
sleep(2)
# 2. 拓展:名字重复
# 问题:import 模块名 时候担心名字重复的问题-不需要(因为功能名一样但是模块名不一样)
import time
print(time)
time = 1 # 这个变量会覆盖模块的功能
print(time)
# 问题:为什么变量也能覆盖模块?-- 在Python语言中,数据是通过 引用 传递的
'''
什么是模块? 模块就是一个python文件,这个文件里面有大量的变量,或者是函数、类,这是一个普通的python文件
可以书写大量的python程序,这个python程序书写完成之后,可以用以下的三种方法进行导入。其他文件能灵活的调用
这个模块当中的功能。
导入模块方法
import 模块名
from 模块名 import 目标
from 模块名 import *
导入包
import 包名.模块名
from 包名 import * ( __all__ = [] : 允许导入的模块或功能列表)
'''
思路:
1.首先先创建一个项目目录StudentManagerSystem。这个是面向对象的学生管理系统,一共有两个角色(两个类),一个是学生,一个是管理系统。为了方便维护代码,一般一个角色一个程序文件。项目由主程序入口,习惯为main.py。
2. 学生类里面有学生的基本信息,当创建一个学生对象的时候,会显示学生的信息(__str__)
3. 管理系统类里面有程序入口,提供功能界面,每个功能由每个函数实现,然后再去调用。功能主要增、删、改、查学生,显示所有学员信息,保存学员信息,加载学员信息。
# 程序入口文件功能的学习,程序入口文件:运行这个文件就可以启动这个管理系统。
# 1. 导入关系系统模块
from managerSystem import *
# 2. 启动管理系统
# 保证是当前文件运行才启动管理系统:if -- 创建对象并调用run方法
if __name__ == '__main__': # 这个__name__意思:在本程序中执行就等于__main__,其他文件调用就不等于__main__.
student_manager = StudentManager()
student_manager.run()
managerSystem.py
from student import *
class StudentManager(object):
def __init__(self):
# 储存学员数据 -- 列表
self.student_list = []
# 程序的入口一般定义为run函数名,这是程序员的习惯。从键盘输入的内容都是字符串,需要用int进行转换
# 一、程序入口函数
def run(self):
# 1. 加载文件里面的学员数据
self.load_student()
while True:
# 2. 显示功能菜单
self.show_menu()
# 3. 用户输入目标功能序号
menu_num = int(input('请输入您需要的功能序号:'))
# 4. 根据用户输入的序号执行不同的功能 -- 如果用户输入1,执行添加
if menu_num == 1:
# 添加学员
self.add_student()
elif menu_num == 2:
# 删除学员
self.del_student()
elif menu_num == 3:
# 修改学员信息
self.modify_student()
elif menu_num == 4:
# 查询学员信息
self.search_student()
elif menu_num == 5:
# 显示所有学员信息
self.show_student()
elif menu_num == 6:
# 保存学员信息
self.save_student()
elif menu_num == 7:
# 退出系统 -- 退出循环
break
# 这里面不涉及对象或对象数据的使用,在面向对象编程的时候,这样的函数需要定义成静态方法。
# 在类里面书写代码,在类里面调用实例方法的写法是self.函数名
# 二、系统功能函数
# 2.1 显示功能函数 -- 打印序号的功能对应关系 -- 静态
@staticmethod
def show_menu():
print('请选择如下功能:')
print('1:添加学员')
print('2:删除学员')
print('3:修改学员信息')
print('4:查询学员信息')
print('5:显示所有学员信息')
print('6:保存学员信息')
print('7:退出系统')
# 2.2 添加学员
def add_student(self):
pass
# 1. 用户输入姓名、性别、手机号
name = input('请输入您的姓名:')
gender = input('请输入您的性别: ')
tel = input('请输入您的手机号:')
# 2. 创建学员列表 -- 类?类在student文件里面 先导入student模块,在创建对象
student = Student(name, gender, tel)
# 3. 将该对象添加到学员列表
self.student_list.append(student)
print(self.student_list)
print(student)
# 2.3 删除学员
def del_student(self):
# 1. 用户输入目标学员姓名
del_name = input('请输入要删除的学员姓名:')
# 2. 遍历学员列表,如果用户输入的学员存在则删除学员对象,否则提示学员不存在
for i in self.student_list:
if del_name == i.name:
# 删除学员对象
self.student_list.remove(i)
break
else:
# 循环正常结束执行的代码:循环结束都没有删除一个对象,所以说明用户输入的目标学员不存在
print('查无此人')
print(self.student_list)
# 2.4 修改学员信息
def modify_student(self):
# 1. 用户输入目标学员姓名
modify_name = input('请输入要修改的学员姓名')
# 2. 遍历列表数据,如果学员存在修改姓名性别手机号,否则提示学员不存在
for i in self.student_list:
if modify_name == i.name:
i.name = input('姓名:')
i.gender = input('性别:')
i.tel = input('手机号:')
print(f'修改学员信息成功,姓名{i.name}, 性别{i.gender}, 手机号{i.tel}')
break
else:
print('查无此人')
# 2.5 查询学员信息
def search_student(self):
# 1. 用户输入目标学员姓名
search_name = input('请输入您要搜索的学员姓名:')
# 2. 遍历列表。如果学员存在打印学员信息,否则提示学员不存在
for i in self.student_list:
if search_name == i.name:
print(f'姓名是{i.name},性别是{i.gender}, 手机号是{i.tel}')
break
else:
print('查无此人!')
# 2.6 显示所有学员信息
def show_student(self):
# 1. 打印表头
print('姓名\t性别\t手机号')
# 2. 打印学员数据
for i in self.student_list:
print(f'{i.name}\t\t{i.gender}\t\t{i.tel}')
# 2.7 保存学员信息
def save_student(self):
# 1. 打开文件
f = open('student.data', 'w')
# 2. 文件写入数据
# 2.1 [学员对象] 转换成 [字典]
new_list = [i.__dict__ for i in self.student_list]
# 2.2 文件写入 字符串数据 (转化成字符串才能写入文件)
f.write(str(new_list))
# 3. 关闭文件
f.close()
# 2.8 加载学员信息
def load_student(self):
# 1. 打开文件:尝试r打开,如果有异常w
try:
f = open('student.data', 'r')
except:
f = open('student.data', 'w')
else:
# 2. 读取数据:文件读取出的数据是字符串 还原列表类型:[{}] 转换 [学员对象]
data = f.read() # 字符串
new_list = eval(data) # 还原列表类型,eval把字符串里面的列表这样的数据类型转换成列表原本类型
self.student_list = [Student(i['name'], i['gender'], i['tel']) for i in new_list] # 获取到每个key的值
finally:
# 3. 关闭文件
f.close()
student.py
'''
需求:
学员信息包含:姓名、性别、手机号
添加__str__魔法方法,方便查看学员对象信息
'''
class Student(object):
def __init__(self, name, gender, tel):
# 姓名、性别、手机号
self.name = name
self.gender = gender
self.tel = tel
def __str__(self):
return f'{self.name}, {self.gender}, {self.tel}'
# aa = Student('aa', 'nv' , 111)
# print(aa)
小拓展__dict__
这个知识点在managerSystem.py文件中用到了,所以学习一下。
'''
拓展:
__dict__是面向对象编程当中类对象或者是实例都拥有的属性,这个属性的作用是收集类对象或者实例对象的属性和方法
以及对应的值,从而返回一个字典。
'''
# 1. 定义类
class A(object):
a = 0
def __init__(self):
self.b = 1
# 2. 创建对象
aa = A()
# 3. 调用__dict__
# 返回类内部所有属性和方法对应的字典
print(A.__dict__)
# 返回实例属性和值组成的字典
print(aa.__dict__) # {'b': 1}
小总结
这是学生管理系统所用的知识点,基本上覆盖了所学的基础知识。查漏补缺,复习巩固。
'''
函数:
定义和调用
参数的使用
面向对象:
定义类
创建对象
定义和调用实例属性
定义和调用实例方法
数据类型:
列表
增加删除数据
列表推导式
字典
字符串
文件操作:
打开文件
读取或写入(读取出来的数据和写入的数据数据类型必须是字符串类型)
关闭文件
'''