8.1.IO流(IO stream)
8.1.1.概念:在本地进行文件存储,形成持久化得读写数据得能力
8.1.2.IO流
- IO流:输入输出流,指一种将数据读入内存和从内存中输出得技术
- 作用:持久化数据,保证数据不在丢失
8.1.3流得分类
- 字节流(b):字节处理,可以操作一切数据,如:音频,图片,可执行文件,字节流操作大数据是,不建议一次性读取
- 字符流(t):字符只能操作UTF-8字符数据,一般不用考虑
8.2.1过程:
8.2.2.缓冲区
- 缓冲区是内存的一部分存储空间,在内存中预留了一定存储空间,该空间用于缓冲输入或输出
- 使用缓存区的必要性
- 由于内存的I/O速度比外设的I/O速度远远大于,同步读写时会造成内存长时间等待浪费性能
- 可能会造成数据溢出或淹没
- 缓冲区分类
- 全缓冲:填满标准I/O缓冲区才会进行实际的传输操着,硬盘的文件默认使用全缓冲
- 行缓冲:当输入输出遇到换行符时就会缓冲
- 无缓冲:用户不提供缓冲,对数据流立即进行读写操作
8.2.3.格式:f=open(filename,mode,encoding)
- open()方法返回值时一个file对象,可以赋值给一个变量(文件句柄)
- filename:文件名,是一个字符串,包含路径
- encoding:编码格式:一般为utf-8
- mode:打开文件方式
模式 | 操作 | 作用 |
f=open('t1.txt','w')
f.write('prthon是一种非常好的语言,\n我喜欢python\n') #写入
f.close() #关闭
8.2.4.b模式
二进制模式:一般用于读取图片,视频等二进制文件
注意:b模式是以byte类型读取文件的,返回的是byte对象不是字符串,必须指定编码格式
s='this is a test'
b=bytes(s,encoding='utf-8')
f=open('test.txt','wb')
f.write(b)
f.close()
8.2.5+模式
- 对于w+模式,在读写之前后会清空原有数据,建议不要使用
- 对于a+模式,永远只会在文件的末尾部写入,有局限性,不建议使用
- 对于r+模式,也就是读写结合模式,配合seek()和tell()方法实现更多操作
8.2.6.文件对象的操作
read(size):读取一定大小的数据,然后作为字符串或字节对象返回,size为可选参数,用于指定读书的数据流,size忽略或为负数时表示改文件所以内容都将被读取并返回
f=open('test.txt','r')
str1=f.read()
print(str1)
str1=f.read(4)
print(str1)
f.close()
f=open('test.txt','r')
str1=f.readline()
print(str1)
f.close()
readlines():将文件所有行,一行一行全部读取到一个列表中,按顺序存储到列表
f=open('test.txt','r')
str1=f.readlines()
print(str1)
f.close()
8.2.7遍历文件
实际上可以将文件对象作为一个迭代器使用
f=open('test.txt','r')
for i in f:
print(i,end=' ')
f.close()
8.2.8.小结:几种不同的读取文件方法,若文件容量小使用read()一次性读写较为方便,若不能确定文件大小则可以使用read(size)反复测试,若是配置文件可以使用readlines()较为方便或者for循环变量
8.2.9.写入方法:write()
作用:将字符串或字节数据写入文件
write()多次操作实际是在内存中完成,并不会立即写入磁盘,只有close()后操作同步到磁盘
格式:文件对象.write('内容')
8.2.10.tell():返回文件读写指针的位置,从文件开头算起的字节数
8.2.11.seek():移动若干字符到指定位置,如:seek(x,1)表示从当前
f=open('test.txt','rb+')
f.write(b'123456789')
f.tell()
print(f.seek(5))
print(f.seek(1))
print(f.seek(2,2))
print(f.seek(3,1))
f.close()
#(x,数字),数字有0,1,2,0表示从文件开头算起,1表示从文件读写指针的位置开始算起,2表示从文件结尾起,默认为0
8.2.12.close():关闭文件对象 ,处理完一个文件后,关闭文件并释放资源,则关闭后若再次尝试读写操作抛出异常,若忘记调用close()则后果可能数据会写入一部分,剩余数据会丢失
8.3.对象序列化
8.3.1.什么是对象序列化:对容器等对象这种抽象的概念转化为真正存储的字符或字节数据的过程
8.3.2.产生原因
- 便于存储,序列化的过程本质就是将文本信息转为二进制数据量,python中程序运行的数据如:序列,字符串,元组等要想永久保存方便以后使用必须进行序列化
- 便于传输,当两个进程进行远距离通信时,彼此可以发送各种类型数据,无论何种类型数据都会以二进制序列化进行传输,接收方收到后进行反序列化转为可以识别的字符集恢复为对象
8.3.3.pickle模块
- 作用:通过pickle模块的序列化操作可以将运行的对象信息存储到文件中,永久把保存,通过pickle反序列化操作可以从文件中恢复对象
- 常用方法:dump dumps load loads
# dumps 序列化为字符数据
import pickle
list1 = [10, 20, 30, 40, 50]
data1 = pickle.dumps(list1)
print(data1)
f = open('test2.txt', mode='wb')
f.write(data1)
f.close()
f = open('test2.txt', mode='rb')
data2=f.read()
print(data2)
f.close()
# loads 反序列化
#loads 序列化为字节数据
# dumps 序列化为字符数据
import pickle
f = open('test2.txt','rb')
show=f.read()
show=pickle.loads(show)
print(show)
f.close()
例:将字符串序列化存储到test3.txt中,读取后反序列化输出
# dump
import pickle
str1 = ['china', 'hello', '123456', 'world']
pickle.dump(str1, open('test3.txt', 'wb'))
f = open('test3.txt', 'wb')
print(f.read())
f.close()
# load
str2 = pickle.loads(open('test3.txt', 'rb'))
print(str2)
8.3.4.json模块
- 作用:json模块将对象序列化为字符数据,方向同上,注意:json用于处理字典数据类型
- 例:
# dump
import json
data1={'username':'张三','age:':17,'number':33}
print(json.dumps(data1))
f = open('test4.txt', 'wb')
f.open('test.txt','wt')
f.write(data1)
f.close()
注意:打开文件方式为wt,字符形式
第九章-面向对象
9.1.面向对象编程思想
9.1.1.编程思想:利用计算机解决问题的一种思维方式,python支持面向过程和面向对象2中方式
9.1.2.面向过程编程思想
- 总结:自顶向下,逐步细化
- 程序的主体是函数,一个函数就是一个封装模块,实现代码重用和模块化编程
- 例: 报名学习,可以分成哪些步骤:开始->学院提出报名,提供相关资料->学生缴纳费用,获得缴费凭证->教师凭借学生缴费凭证进行分班->班级增加学生信息->结束,以上步骤依次执行即可
9.1.3.面向对象编程思想
- 面向对象就是编程时尽可能去模拟现实世界,现实世界中,任何一个操作或者业务逻辑的实现都需要一个实体来完成,实体是动作过的支配者,没有实体就没有动作发生
- 思考上述报名过程,动词:提出,提供,获得,缴费,增加等
- 有动词就有实现带动做的实体
- 例:面向对象报名案例分析
- 第一步:分析哪些动作由哪些实体发出的:
- 学生:提出报名
- 学生:提供资料
- 学生:缴费
- 机构:收费
- 教师:分班
- 班级:增加学生信息
- 一共四个实体:学生,机构,教师,班级
- 第二步:定义这些实体,为其增加相应的属性和功能
- 属性:实体的固有特征,就是以前面向过程中的
- 如:
实体 属性 手机 价格,品牌,操作系统,颜色,尺寸 人 身高,体重,姓名,年龄,学历,电话,籍贯等 - 功能:就是实体可以完成的动作,在面向对象属术语中,功能就是封装的函数或方法
- 报名的实体与属性
-
第三步:让实体执行相应的功能和动作
-
学生:提出报名
-
学生:提供相应资料
-
教师:等级学生信息
-
机构:收费
-
教师:分配教师
-
班级:增加学生信息
-
- 第一步:分析哪些动作由哪些实体发出的:
9.1.4面试题:面向过程与面向对象的区别
- 都可以实现代码重用和模块编程,面向对象的模块化更深,数据也更封闭更3安全
- 面向对象思维方式更贴近现实生活更容易解决大型的复杂业务逻辑
- 从前期开发角度来看,面向对象比面向过程更复杂,但从维护和扩展角度来说,面向对象比面向过程更简单
- 面向过程的代码执行效率比面向对象更高
9.2.面向对象专业术语
9.2.1.组成:
- OOA:面向对象分析
- OOD:面向对象设计
- OOP:面向对象编程
9.2.2.对象(object)
- 概念:是一个抽象概念,实现世界万物皆为对象,对象就是实际存在的实体,如:一个人
- 一个对象分为2部分
- 静态部分:属性,客观存在,不可忽视,如:人的性别
- 动态部分:行为,对象执行的操作,如:人跑步
- 对象使用属性保存数据,使用方法管理数据
9.2.3.类
- python中使用类产生对象,使用类规定对象的属性和方法,想要的得到对象必须先有类
- 引入类的原因
- 实现实体都要有一个类别
- 类:具有相同或相似的属性和动作的一组实体的集合
- 一个对象所具有的特征信息都是由类决定的,但对象又可以
9.3.类的定义和使用
9.3.1.面向对象开发步骤
- 第一步:设计一个类
- 第二步:使用类名创建对象,创建对象又有2步
- 内存中为对象分配空间
- 调用初始化对象_ _init_ _()为对象初始化
9.3.2.定义一个类
经典类
class 类名:
...类的信息...
代码
新式类:
class 类名():
...类的信息...
代码
- 注意:
- 类名字命名时遵守一般标识符
- 为了和方法区别开来,应使用大驼峰写法,类名中每个单词首字母大写,不能使用下划线,实例名和方法名都应小写并在单词之间增加下划线
- 基本框架
-
class Person(): #属性 #方法(函数) def eat(self): print('我喜欢吃') def drink(self): print('我喜欢喝可乐') class Geese: '''大雁类''' pass
-
特别注意:
-
类本质也是一个对象
-
python一切皆为对象,类是一个特殊的对象即
-
类对象运行也会被加载到内存
-
类对象在内存‘中只有一份,可以创建出多个对象实例
-
9.3.3.类的实例化
- 定义完类之后并不会立即创建一个实例对象,必须根据类实例化创建出对象才可以进行处理
- 类只能是对象的一种范式,类本身什么也做不了,必须利用类的到对象,改过程成为类的实例化
- 格式:
- 对象名=类名()
- 例:
# 1.定义一个类
class Person():
#方法关联方法
def eat(self):
print('我喜欢吃')
def drink(self):
print('我喜欢喝可乐')
#实例化对象
p1=Person()
# 调用对象的方法实现功能
p1.eat()
p1.drink()
- 每一个对象都有自己的独立空间,保存各自的不同属性,多个对象的方法在内存中只有一份,在调用时,需要把对象的引用传递给方法内部
9.3.4.类的self关键字
- self是一个python关键字,作用:指向类实例对象本身,用于访问类中的属性和方法,在方法调用时会自动传递参数self
# 1.定义一个类
class Person():
#定义关联方法
def eat(self):
print('我喜欢吃')
print(self)
def drink(self):
print('我喜欢喝可乐')
#2.实例化对象
p1=Person()
p2=Person()
p1.eat()
p2.eat()
总结:类中self就是实例化的对象本身
9.3.5.创建_ _init_ _ () 方法(初始化方法)
- python中_ _xx_ _() 函数成为魔术方法,指具有特殊功能的函数
- 类创建后可以手动创建一个 _ _init_ _()方法,在创建一个对象时默认被调用的不需要手动调用
- 例:
class Geese: '''大雁类''' def __init__(self,beak,wing,claw): print('大雁类') print(beak) print(wing) print(claw) beak1='有较长的嘴' wang1='翅膀长而尖' clwa1='爪子为' wil=Geese(beak1,wang1,clwa1)
-
_ _init_ _()方法必须包含一个参数self,位置必须是第一个,self本质是指向实例对象本身
-
_ _init_ _()方法双线划线开头和结尾,下划线之间不能有空格
-
_ _init_ _ ()方法可以自己定义一些参数,都好隔开
-
例
# 1.定义一个类
class Person():
#初始化实例对象
def __init__(self,name,age):
self.name=name
self.age=age
#2.实例化对象并传入初始化的参数
p1=Person('悟空',500)
# 3.调用P1对象自身的属性
print(p1.name)
print(p1.age)
9.3.6.创建类的实例方法
- 类的成员主要由实例方法和数据组成
- 实例方法本质是类中定义的函数
- 格式
def 方法名 (self,其它形参)
方法体
- 方法名:一般小写字母开头
- self:必要参数,标识类的实例
- 其它参数:多个参数使用都好隔离
- 方法体:实现方法具体的功能程序段
- 实例化与一般函数的区别
9.3.7.创建类的静态方法
- 作用:在程序设计开发时,在类中设计一种方法,该方法:
- 不需要访问实例属性或调用
- 不需要访问类属性或类调用
- 一般用于打印提示,帮助信息等
- 格式:@staticmethod,用于修饰类中的方法,使其在不创建对象的情况下进行调用,优点:执行效率高,该方法称为静态方法,静态方法不可以应用
#开发一个游戏
class Game(object):
#开始游戏,打印游戏功能菜单
@staticmethod #装饰器声明下面方法为静态方法
def menu():
print('1.开始游戏')
print('2.游戏暂停')
print('3.退出游戏')
Game.menu() #不需要创建对象,通过类名.方法名调用
9.3.8.创建类的属性
- 概念:定义在类中并且在函数外部的属性变量,类属性可以在类的所有实例对象之间共享,是一种公共属性,一般记录类的相干特征
- 类属性可以通过类名或对象名访问
- 例
class Geese: '''大雁类''' neck='脖子较长' wing='翅膀的频率高' leg='腿位于身体中心支点' geese1=Geese() print(Geese.neck) #通过 类名.属性名 访问 print(Geese.wing) #通过 类名.属性名 访问 print(Geese.neck) #通过 类名.属性名 访问
-
示例图
类属性一旦变更,所有对象的属性都会变化
class Geese:
'''大雁类'''
neck='脖子老长较长'
wing='翅膀的频率高'
leg='腿位于身体中心支点'
geese1=Geese()
geese2=Geese()
print(geese1.neck)
print(geese2.neck)
注意:不能使用对象.属性=值 方法
9.
class Person:
pass
p1=Person()
p1.name='老王'
p1.age=22
p1.address='192.168.80.133'
p2=Person()
print(p2.name) #报错,name是p1的对象属性,私有
class Person:
def speak(self):
print(f'我的名字:{self.name},我的年龄:{self.age},我的地址:{self.address}')
p1=Person()
p1.name='悟空'
p1.age=500
p1.address='花果山水帘洞1号'
p1.speak()
9.4.魔术方法
9.4.1.在python中_ _ xxx_ _()的函数称为魔术方法,指具有特殊功能的函数
9.4.2._ _str_ _()方法
- 作用:类中若定义的_ _str_ _()方法,则会打印从该方法,则会打印从该方法return的数据
- 例
class Car():
# 首先定义一个初始化方法,用于初始化实例对象的属性
def __init__(self, brand, model, color):
self.brand = brand
self.model = model
self.color = color
def __str__(self):
return f'汽车品牌:{self.brand},汽车型号:{self.model},汽车颜色:{self.color}'
model3 = Car('奔驰', 's600', '黑色')
print(model3)
- 上例中print(model3)若类中无_ _str_ _()方法则默认输出对象的首地址,若有则输出return后的结果
9.4.3._ _del_ _()方法
class Car():
# 首先定义一个初始化方法,用于初始化实例对象的属性
def __init__(self, brand, model, color):
self.brand = brand
self.model = model
self.color = color
def __str__(self):
return f'汽车品牌:{self.brand},汽车型号:{self.model},汽车颜色:{self.color}'
del __del__(self):
print(f'{self}对象已删除')
model3 = Car('奔驰', 's600', '黑色')
print(model3)
# 删除对象model3
del model3 #自动调用__del__()方法
- 注意:_ _del_ _ ()方法一般用于输出提示,关闭文件,关闭数据库等后续操作
9.5面向对象程序设计案例
9.5.1.例:定义学院信息类,包含姓名,成绩属性。定义成绩打印方法,打印等级成绩(90以上优秀,80以上良好,70以上中等,60以上及格)
实体:学员
属性:
方法:
# 1.创建学员类
class Student():
# 2.定义学员属性
def __init__(self, name, score):
self.name = name # 所有对象的名字来自哪里
self.score = score
def print_grade(self):
if self.score >= 90:
print(f'学员姓名:{self.name},学员成绩:{self.score},优秀')
elif self.score >= 80:
print(f'学员姓名:{self.name},学员成绩:{self.score},良好')
elif self.score >= 70:
print(f'学员姓名:{self.name},学员成绩:{self.score},中等')
elif self.score >= 60:
print(f'学员姓名:{self.name},学员成绩:{self.score},及格')
else:
print(f'学员姓名:{self.name},学员成绩:{self.score},补考')
name1 = input('请输入姓名')
score1 = input('请输入成绩')
tom = Student(name1, score1)
tom.print_grade()
9.5.2.例2.小明体重120公斤,每次跑步减掉0.5公斤,每次吃饭增加1公斤
实体:小明
属性
方法:
跑步
吃饭
class Person():
def __init__(self, name, weight):
self.name = name # 所有对象的名字来自哪里
self.weight = weight
def run(self):
self.weight-=0.5
def eat(self):
self.weight+=1
def __str__(self):
return f'名字:{self.name},目前体重:{self.weight}KG'
xiaoming=Person('小明',120)
print(xiaoming) #利用str魔术方法返回信息
xiaoming.eat()
print(xiaoming)
xiaoming.run()
print(xiaoming)
9.5.3.例3:编写prime类实现输出大于m且紧随m的k个素数
实体:数字
属性: m k
方法:判断实现大于m且紧随m的k个素数
class Prime():
def __init__(self, start_value, number):
self.start_value = start_value # 所有对象的名字来自哪里
self.number = number
def prime_number(self):
count = 0
i = self.start_value + 1
while count < self.number:
for j in range(2, i):
if i % j == 0:
break
else:
count += 1
print(i, end=' ')
i+=1
m = int(input('请输入起始值'))
k = int(input('请输入查找个数'))
prime1=Prime(m,k)
prime1.prime_number()
95.4.例:编写Mysort类实现整数升序排序
实体:list列表
属性:list len
方法 :选择法升序
class Mysort():
def __init__(self, list1):
self.list1 = list1
def selection_sort(self):
if len(self.list1) == 0:
return '数据不能为空'
self.list1 = list(self.list1) # 将字符串数字转为字符串列表
self.list1 = [int(self.list1[i]) for i in range(len(self.list1))]
# 选择法排序
for i in range(len(self.list1) - 1):
for j in range(i + 1, len(self.list1)):
if self.list1[i] > self.list1[j]:
self.list1[i], self.list1[j] = self.list1[j], self.list1[i]
return self.list1
li = input('请输入需要排序的序列:')
mysort1 = Mysort(li)
print(mysort1.selection_sort())