一、上堂回顾
1.默写题目
1.简述类属性和实例属性之间的区别
a.定义的位置 b.访问方式不同 c.在内存中出现的时机不同 d.优先级不同
2.简述成员方法,类方法和静态方法之间的区别
a.语法 b.调用方式 c.在继承关系中【相同点】
3.采用装饰器的方式书写一个单例设计模式
#1.闭包 def singleton(cls): #2.单例的实现思路 instance = {} def getInstance(*args,**kargs): if cls not in instance: instance[cls] = cls(*args,**kargs) return instance[cls] return getInstance @singleton class Person(object): pass
2.知识点回顾
1.重写:【override】
在继承的类中,在子类中将函数重新实现一次
2.重载:[overload]
将系统的内置函数重新实现一次
3.多态
父类的引用指向子类的对象
重写和重载都是多态的体现形式
4.获取对象信息
type()
isinstance() 一般用在if语句中
作业:
textDemo01.py
""" 3.使用封装的思想结合列表完成下面题目 学生类:姓名、年龄、学号、成绩 班级类:班级名称、学生列表 显示所有学生 根据学号查找学生 添加一个学生 删除一个学生(学生对象、学号) 根据学号升序排序 根据成绩降序排序 """ from homework.student import Student from homework.grade import Grade #1.创建学生对象 stu1 = Student("小明",10,1001,80) stu2 = Student("jack",20,1003,60) stu3 = Student("bob",15,1002,99) stu4 = Student("tom",30,1004,75) #2.创建班级对象 gra = Grade("三年一班",[stu1,stu2,stu3,stu4]) #3.调用功能 gra.showAll() gra.searchBystuid(1002) stu5 = Student("abc",25,1005,80) gra.addStu(stu5) #gra.delStu(1003) #gra.sortBystuid() gra.sortByScore()
student.py
class Student(object): def __init__(self,name,age,stuid,score): self.name = name self.age = age self.stuid = stuid self.score = score def __str__(self): return "%s %d %d %d" %(self.name,self.age,self.stuid,self.score)
grade.py
class Grade(object): def __init__(self,name,stulist): self.name = name self.stulist = stulist #显示所有学生 def showAll(self): print("所有学生的信息为:") for stu in self.stulist: print(stu) #根据学号查找学生 def searchBystuid(self,stuid): for stu in self.stulist: if stuid == stu.stuid: print("搜索结果如下:") print(stu) # 添加一个学生 def addStu(self,stu): self.stulist.append(stu) print("添加之后的学生如下:") self.showAll() # 删除一个学生(学生对象、学号) def delStu(self,stuid): for stu in self.stulist: if stuid == stu.stuid: self.stulist.remove(stu) print("删除之后的学生如下:") self.showAll() # 根据学号升序排序 def sortBystuid(self): for i in range(0,len(self.stulist) - 1): for j in range(0,len(self.stulist) - i - 1): if self.stulist[j].stuid > self.stulist[j + 1].stuid: self.stulist[j],self.stulist[j + 1] = self.stulist[j + 1],self.stulist[j] print("排序之后的结果为:") self.showAll() # 根据成绩降序排序 def sortByScore(self): for i in range(0,len(self.stulist) - 1): for j in range(i + 1,len(self.stulist)): if self.stulist[i].score < self.stulist[j].score: self.stulist[i],self.stulist[j] = self.stulist[j],self.stulist[i] print("排序之后的结果为:") self.showAll()
二、错误和异常
1.概念
有两种错误很容易辨认:语法错误和异常
异常:代码没有出现错误,但是,当程序 运行起来之后,会在控制台上报出错误,这种错误就被称为异常
异常的特点:当程序在执行过程中遇到异常,而且异常没有被处理,则程序会终止在出现异常的地方,代码不会继续向下执行
解决问题:当程序遇到异常的时候,让程序越过异常继续向下执行
本质【工作机制】:只是将异常屏蔽掉,不要影响其他代码的执行,并没有真正的处理
2.常见异常
AttributeError:指定对象没有指定的属性
StopIteration:迭代器没有更多的值进行遍历
ZeroDevisionError:不能除以或者取模0
KeyError:字典中没有指定的键
NameError:没有声明或者初始化变量【某个对象没有某个指定的属性】
UnboundLocalError:访问未初始化的本地变量
SyntaxError:Python语法错误
TypeError:对类型进行无效的操作
3.异常处理方式【掌握】
异常处理的方式:捕获和抛出
3.1try-except-else
语法:
try:
语句
except 错误表示码1 as 变量名:
语句1
except 错误表示码2 as 变量名:
语句2
......
else:
语句n
说明:
a.try对应的代码块被称为代码监测区域,用来监测其中的代码是否有异常【将可能存在异常的代码写在try代码块中】
b.如果try中的代码出现了异常,则try中的代码会终止在出现异常的代码处,则直接执行except代码块,具体执行哪个except代码块,取决于出现了什么样的异常
注意:此处的except块并不是真正处理了异常,只是做了屏蔽【拦截】,可以让后面的代码正常执行
c.else可有可无,根据具体的需求而定
代码演示:
#1.使用except带一个异常类型 try: #可能存在异常的代码 #num = int(input("请输入一个数字:")) #print(10 / num) pass except ZeroDivisionError as e: #此处的e就相当于一个ZeroDivisionError的对象 #注意:所有异常的类中将__str__重写过了,返回一个异常的描述字符串 print(e) #division by zero print("hello") #2.使用多个except异常类型 #工作原理;如果try中代码出现了异常,则在except分支中从上往下挨个进行匹配错误码,如果匹配上了,则整个try-except结束 try: #可能存在异常的代码 #num = int(input("请输入一个数字:")) #print(10 / num) pass except KeyError as e: print(e) except ValueError as e: print(e) except ZeroDivisionError as e: print(e) #division by zero except UnboundLocalError as e: print(e) #3.except不带任何异常类型 #工作原理:不管try中出现什么样的异常,都会执行except块 try: #可能存在异常的代码 #num = int(input("请输入一个数字:")) #print(10 / num) pass except: print("出现了异常") #4.一个except后面可以跟多种错误码 #工作原理;只要try中出现的异常匹配上元组中的任意一个错误码即可 try: #print(10 / 0) pass except (ZeroDivisionError,KeyError,ValueError): print("出现了异常") #5.else分支 #工作原理:只有当try中的代码没有异常出现的时候,才会执行else分支 try: print(10 / 5) except (ZeroDivisionError,KeyError,ValueError): print("出现了异常") else: print("else被执行了") #6.除了在try中直接检测可能存在异常的的代码,也可以检测可能存在异常的代码所在的函数 def test(): print(10 / 0) try: #test() pass except ZeroDivisionError as e: print(e) #7.所有异常的父类是BaseException【Exception】,如果BaseException出现在except语句的第一个,则直接会被执行 try: print(10 / 0) except BaseException as e: print("~~~~~") print(e) except ZeroDivisionError as e: print(e)
3.2try-except-finally
作用:一般用来定义清理行为,表示代码执行完成之后都需要做的清理行为
语法:
try:
语句
except 错误表示码1 as 变量名:
语句1
except 错误表示码2 as 变量名:
语句2
......
finally:
语句n
说明:区别于else分支,不管try中代码有没有异常,finally块都会被执行
代码演示:
#1.直接使用 try: print(10 / 5) except BaseException as e: print(e) finally: print("finally被执行了") #2.特殊情况 #注意:如果在try-except-finally语句中,在try或者except语句中出现return,finally仍然会被执行 #使用场景:文件关闭,数据库关闭,为了避免资源的浪费 def show(): try: print(10 / 4) return except BaseException as e: print(e) finally: print("finally被执行了~~~~~~") show() print("&&&&&&&&&&&&&&7") #3.特殊情况:如果try中的异常没有匹配到相应的except语句,那么这个异常会在finally执行之后再次出现 try: print(10 / 0) except KeyError as e: print(e) finally: print("over") """ Traceback (most recent call last): File "C:/Users/Administrator/Desktop/XA-Python1804/Day14Code/exception/try-exceptDemo02.py", line 30, in <module> print(10 / 0) ZeroDivisionError: division by zero """
3.3抛出异常
raise:抛出一个异常
代码演示:
#语法:raise 异常对象 ======》等价于实实在在存在的一个异常 10 / 0 #异常错误码("异常的信息描述") try: raise NameError("变量没有被初始化") except NameError as e: print(e) #raise表示实实在在的抛出了异常,为了不影响其他代码的执行,最终还是要通过try-except进行捕获 #raise的使用场景:自定义异常中
3.4assert断言【了解】
代码演示:
def fun(num,divnum): #断言 #预言:预言成功,则获取结果,预言失败,则出现一个AssertionError异常,异常的信息描述是自定义的 assert (divnum != 0),"除数或者分母不能为0" return num / divnum #print(fun(10,4)) print(fun(10,0))
4.异常嵌套
try中嵌套try
except中嵌套try:常用
代码演示:
print("我想去拉萨") try: print("我准备乘飞机过去") raise Exception("由于天气大雾,飞机无法起飞") print("到拉萨了,拉萨真漂亮") except Exception as e: print(e) try: print("我准备乘火车过去") raise Exception("由于大暴雨,铁路断了") print("到拉萨了,拉萨真漂亮") except Exception as e: print(e) print("我骑自行车去") print("到拉萨了,拉萨真漂亮")
5.自定义异常
实现步骤:
a.自定义一个类,继承自Exception类或者BaseException
b.书写构造函数,设置一个参数,用于保存异常信息
c.重写str函数,返回异常信息
d.定义一个成员函数,用来处理异常
代码演示:
class MyException(Exception): def __init__(self,msg): #调用父类中的构造函数,目的是将系统的异常机制引用过来 super(MyException,self).__init__() self.msg = msg def __str__(self): return self.msg def handle(self): print("处理异常") try: raise MyException("自己的异常类型") except MyException as e: print(e) e.handle()
三、文件读写【掌握】
1.概述
Python中内置了文件读写的功能
现代的系统不允许普通的程序直接访问磁盘的,所以,读写磁盘上的文件首先会请求打开一个文件的对象【也被称为文件描述符】,然后,通过系统提供的功能就可以读写文件
2.读文件
2.1过程
a.打开文件:open()
b.读取文件内容:read()
c.关闭文件:close()
注意;文件使用完毕之后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统在同一个时间段内打开的文件是有限的
2.2使用
代码演示:
#一、打开文件 """ open(path,flag[,encoding,errors]) path:需要读取的文件的路径【相对路径和绝对路径】 flag:打开方式 r:只读的方式打开,注意:读取的文件必须存在 rb:以二进制的形式打开一个文件,用于只读,注意:读取的文件必须存在 r+:打开一个文件用于读写,注意:读取的文件必须存在 w:只能写入内容,注意:如果该文件存在则覆盖,如果不存在则会自动创建 wb:以二进制的方式打开一个文件,用于写入,注意:如果该文件存在则覆盖,如果不存在则会自动创建 w+:打开一个文件用于读写,注意:如果该文件存在则覆盖,如果不存在则会自动创建 a:打开一个文件,向其中追加内容 说明:rb和wb 表示使用二进制的形式打开文件,主要用来打开多媒体资源【图片,视频,音频等】 encoding:编码格式,可写可不写 errors:错误处理,可写可不写 """ #注意:encoding一般使用关键字参数传参;打开文件的时候采用的编码格式必须和文件本身的编码格式一致,否则出现乱码 f = open("致橡树.txt","r",encoding="gbk") print(f) """ 1.当使用r的方式打开文件的时候,后面的encoding可加可不加 如果文件的格式为gbk的,可以不加 如果文件的格式时utf-8的,最好加上encoding="utf-8" 2.当使用rb/wb的方式打开文件的时候,后面的encoding不添加 """ #二、读取文件内容 #1.一次性读取全部的内容 #str1 = f.read() #print(str1) #2.读取指定字符数 #如果不指定参数,则一次性读取全部的内容,如果指定参数,以字符串返回指定数量的数据,并且每一行的结尾都有一个换行符"\n" #str2 = f.read(5) #print(str2) #3.读取整行 #注意:不管一行有多少个字符,一次性读取一行,以"\n"作为参照进行换行 # readline() """ str3 = f.readline() print(str3) str3 = f.readline() print(str3) str3 = f.readline() print(str3) str3 = f.readline() print(str3) """ #4.读取一行中前指定的字符 str4 = f.readline(3) print(str4) str4 = f.readline(3) print(str4) str4 = f.readline(3) print(str4) #5.读取所有行并返回列表,显式的出现\n #readlines() str5 = f.readlines() print(str5) #三、关闭文件 f.close() #一个完整的过程 try: f1 = open("致橡树.txt","r",encoding="gbk") print(f1.read()) except FileNotFoundError as e: print(e) #找不到指定的文件路径 #f1 = None except LookupError as e: print(e) #指定了未知的编码 except UnicodeDecodeError as e: print(e) #读取文件的时候解码错误 finally: if f1: f1.close() #简写方式 #好处:不需要手动调用close关闭文件,文件读取完成之后会自动关闭 with open("致橡树.txt","r",encoding="gbk") as f: print(f.read())
3.写文件
3.1过程
a.打开文件:open()
b.将数据写入缓存:write()
c.刷新文件内部缓存:flush()
d.关闭文件:close()
3.2使用
代码演示:
#注意:向一个文件中写入内容,文件可以不存在,会自动创建 path = "file1.txt" #1.打开文件 wb a #注意:w表示将原来的内容全部替换,a表示在文件末尾进行追加 f = open(path,"a",encoding="gbk") #2.写入数据 #注意:如果写入文件的数据需要换行的话,则需要手动添加\n f.write("hello写入文件的数据需要换行的话") #3.刷新缓冲区【加速数据的流动,保证缓冲区的畅通】 #直接将内部缓冲区的内容立刻写入文件,而不是被动的等待自动刷新写入 f.flush() #4.关闭文件 f.close() #简写形式 """ with open(path,"w",encoding="utf-8") as f: f.write("") f.flush() """
4.编码和解码
字符串类型和字节类型之间的转换
字符串类型转换为字节类型:编码【encode】
utf-8: 存储中文3个字节
gbk;存储中文2个字节
字节类型转换为字符串类型:解码【decode】
注意:保证设置的编码格式和文件的编码格式相符,否则出现乱码
代码演示:
path = r"file2.txt" #编码:字符串----》字节 with open(path,"wb") as f1: s1 = "今天是个好日子,today is a good day" f1.write(s1.encode("utf-8")) f1.flush() #解码:字节----》字符串 with open(path,"rb") as f2: data = f2.read() print(data) print(type(data)) newData = data.decode("utf-8") print(newData)
5.练习
代码演示:
# 需求:需求文件内容的拷贝
import osdef myCopy(srcPath,desPath):
#判断源文件是否存在
if not os.path.exists(srcPath):
print("源文件不存在")
return#判断源路径是否是文件
if not os.path.isfile(srcPath):
print("源路径是文件夹,不是文件")
return#打开文件
srcFile = open(srcPath,"rb")
desFile = open(desPath,"wb")#获取源文件的大小
size = os.path.getsize(srcPath)
#循环读取文件,并将读取出来的内容写入到目标文件中
while size > 0:
content = srcFile.read(1024)
desFile.write(content)
desFile.flush()
size -= 1024#关闭文件
srcFile.close()
desFile.close()