文章目录
文件读写
Python内置了文件读写的函数,用法和c语言是兼容的
工作原理:从做系统不允许在磁盘上直接读写文件,多以读写就是请求os打开一个文件对象【被称为文件的描述符】,然后,通过os提供的接口从这个文件对象中读取数据【读文件】,或者将数据写入到文件中【写文件】
1、常用文件读写
1.1、读文件
步骤:
a、打开文件:open()
b、读取内容:read()
c、关闭文件:close()
import os
import pprint
"""
读文件:从磁盘到内存
写文件:从内存到磁盘
IO:Input/Output
IoError:当文件读取完毕,还继续读取
"""
# 一、打开文件
"""
open(path,flag,encoding,errors)
path:需要打开的文件的路径,绝对路径、相对路径都可以,一般r“path”
flag:以文件的方式:
r:以只读的方式打开文件,文件描述符出现在文件的开头
rb:以二进制的方式打开一个文件用于只读,文件描述符出现在文件的开头
r+:打开一个文件用于读写,文件描述符出现在文件的开头
encoding:编码格式,常用utf-8和gbk
errors:惊醒读取文件的时候的无措处理,一般用异常,可忽略
"""
path = r"C:\Users\weichen\Desktop\shopping2\shopping_car\致橡树.txt"
# 以只读的方式打开
# f是一个变量,指向一个被打开的文件,被称为文件对象
f = open(path, "r", encoding="gbk")
"""
注意:
1、如果flag采用的是rb,encoding则必须省略,否则报错
2、如果flag采用的是r,如果文件格式是gbk,则可以省略encoding="gbk",
如果文件格式是utf-8,则不能省略encoding = "utf-8"
"""
# 二、读取文件内容
# 1、read
# 1.1 默认读取文件中的所有内容
# 使用场景:读取内容较少的文件
# str1 = f.read()
# print(str1)
# 1.2一次读取指定字节的内容
# 使用场景:结合循环,读取内容较多的文件
# str1 = f.read(3)
#采用read(num)方式读取文件的全部内容,借助于循环
#在读取数据量大的文件时,一次读取的大小一般为1024
# size = os.path.getsize(r"C:\Users\weichen\Desktop\shopping2\shopping_car\致橡树.txt")
# print(size)
# num = 816
#
# while size>0:
# str1 = f.read(num)
# print(str1)
#
# size -= num
# 2、readline
# 2.1一次读取一行内容
# str2 = f.readline()
# print(str2)
# 借助于循环读取全部的内容,入伏哦返回值为假,则表示没有内容可读
# result = f.readline()
#
# while result:
# print(result)
# result = f.readline()
# 2.2 readline(num),类似read(num),但是一般不这么用,使用目的是为了读取一行内容
# 2.3 readlines,按照行进读取,结果为一个列表,其中会显示换行符和空格
str3 = f.readlines()
# print(str3)
pprint.pprint(str3)
# 三、关闭文件
# 注意:关闭的文件的目的有时候为了系统资源的浪费
f.close()
1.2写文件
步骤:
a.打开文件:open()
b写入内容:write()
flush
c.关闭文件:close()
# 写文件
# 一、打开文件
"""
open(path,flag,encoding,errors)
flag:文件的打开方式
w:一写入的方式打开一个文件,文件描述符存在文件的开头
wb:以二进制的方式打开一个文件的写入,文件描述符存在文件的开头
w+: 打开一个文件用于读写,文件描述符出现在文件的开头
a:append,在源文件内容的后面追加内容
"""
f = open(r"file1.txt","w",encoding="utf-8")
# 二、写入内容
f.write("你好hello1234")
# 一般写入内容后刷新,加快写入速度
f.flush()
# 三、关闭文件
f.close()
"""
总结:
1、不管是读取文件还是写入文件,都需要打开文件,打开的方式取决于需要进行的操作
2、如果时读取文件,则文件必须存在,二如果时写入文件,则文件可以不存在,在写入的过程会自动创建
3、在写入文件的过程中,如果采用的时w,则覆盖,a,追加
4、在进行文件读写的时候,一定要注意使用的编码格式和文件本身的编码格式需要保持一致,否则乱码
"""
with语句
# 文件读写的简写形式
# with.....as...
"""
通过with...as...,简化文件读写过程中的异常
优点:当文件读写完毕之后,可以自动关闭文件,不需要手动关闭
"""
# 读文件
# f知识一个变量,只是只想打开的文件对象
with open("致橡树.txt","r", encoding="gbk") as f:
print(f.read())
# 写文件
with open("file1.txt","w",encoding="gbk") as f:
f.write("浪里个浪")
f.flush()
# 注意:一旦代码执行with...as..代码块,则文件会自动关闭,但是,对于变量不会引入新的作用域
2、csv文件的读写
读取文件
# 读取csv文件
import csv
def readcsv1(path):
# 1.打开文件
csvfile = open(path,"r")
# 2.读取文件内容
# 区别于普通文件,但会一个迭代对象,如果要获取具体内容,则可以遍历该可迭代对象
result = csv.reader(csvfile)
print(result)
for content in result:
# 可迭代对象当中的元素为列表
print(content)
# 关闭文件
csvfile.close()
if __name__ == "__main__":
readcsv1(r"csv1.csv")
# 二、# 读取csv文件
import csv
def readcsv1(path):
with open(path,"r") as f1:
result = csv.reader(f1)
for content in result:
print(content)
if __name__ == "__main__":
readcsv1(r"csv1.csv")
写入文件
# 写入csv文件
import csv
# 注意,向csv文件中写入任意的可迭代对象
def writecsv1(path):
# 打开文件
csvfile = open(path,"w")
# 写入
# 获取写入对象
result = csv.writer(csvfile)
# 写入
# 列表
# 字符串: 打碎重写
# 字典:只写key
result.writerow(["aaa", 'bbb', 'dd', 'cc'])
# 关闭文件
csvfile.close()
if __name__ == "__main__":
writecsv1("csv2.csv")
3、编码和解码
乱码:utf-8存储中文 3个字节,gbk存储中文占用2个字节
注意:编解码格式要保持一致,如果不一致,修改文件本身的编码格式
path = r"text03.txt"
#1.编码
with open(path,"wb") as f1:
str1 = "今天是个好日子today is a good day"
f1.write(str1.encode("utf-8"))
#
# with open(path,"w",encoding="utf-8") as f1:
# str1 = "今天是个好日子today is a good day"
# f1.write(str1)
#2.解码
# with open(path, "rb") as f1:
# data = f1.read().decode("utf-8")
# print(data)
with open(path, "r", encoding="utf-8") as f1:
data = f1.read()
print(data)
pickle模块
在python中,如果要实现序列化和反序列化,可以使用pickle和json
【面试题:简述什么时序列化和反序列化】
序列化:将对象持久化到磁盘上,【写:weite】,英文表示为picking,serialiation
反序列化:将磁盘上的对象读取出来【读:read】,英文表示:unpicking
import pickle
"""
pickle提供了简单的持久化功能,可以将对象以文本的形式存储到磁盘上
pickle只能在Python中使用,
Python中所有的数据类型【list,tuple,dict,set,str,对象】都可以通过pickle模块持久化到磁盘上
注意:通过pickle序列化之后的数据,人一般无法识别,只能计算机识别【区别于乱码】
"""
class Person(object):
def __init__(self,name,age):
self.name = name
self.age = age
def show(self):
print("姓名:%s,年龄:%s" % (self.name,self.age))
p = Person("zhangsan",10)
#1.以普通文件的方式操作对象
#缺点:write只能写入字符串
#f = open(r"file1.txt","w",encoding="utf8")
#f.write(p)#TypeError: write() argument must be str, not Person
#f.close()
#2.思考问题:如果向文件中写入一个对象,该如何做?---》pickle模块
#2.1序列化【写】
"""
pickle.dump(obj,file)
obj:将要写入文件的对象
file:obj将要写入的文件对象,注意:file必须以二进制的方式打开,为wb
"""
#a。打开文件
f1 = open(r"obj.txt","wb")
#b.写入对象
pickle.dump(p,f1)
#c.关闭文件
f1.close()
#2.反序列化【读】
"""
pickle.load(file)
file:将要读取的文件对象,注意:file必须以二进制的方式打开,为rb
"""
#a.打开文件
f2 = open(r"obj.txt","rb")
#b。读取对象
result = pickle.load(f2)
print(result)
result.show()
#c.关闭文件
f2.close()
"""
w,w+,wb都会覆盖源文件中的内容,
r,r+,rb都必须保证源文件存在
w,w+,wb,a如果文件不存在,会自动创建
"""
json模块
思考问题:将文本或者二进制数保存到文件中,使用write操作,如果将一个列表或者字典直接保存到文件中该如何实现?------》使用json格式保存数据
JSON:JavaScript Object Notation,本来是JavaScript语句中船舰对象的一种字面量方式,被广泛应用于跨平台的语言的数据交换【因为JSon时纯文本,任何系统任何编程语言都可以处理纯文本】
使用场景:在两种不同的编程语言之间传递对象,将数据序列化为josn,json表示出来就是一个字符串,可以被所有的语言读取,也可以存储到磁盘或者网络传输
在web开发中,不仅使用json,还使用xml,但是使用json较多,json更快,而且可以直接在web中读取
Python中的数据类型和json的数据类型的区别:
json Python
object dict
array list
string str
number int/folat
true/false True/False
null None
注意:json和pick将数据序列化之后的区别
import pickle
dict2 = dict(name="jack",age=10,score=100)
with open(r"pickle1.txt","wb") as f2:
pickle.dump(dict2,f2)
import json
#一、基本用法
#1.写【序列化】
"""
dump():将Python对象按照json格式序列化到文件中
dumps():将Python对象处理成json格式的字符串
"""
#1.1
dict1 = dict(name="jack",age=10,score=100)
print(dict1)
r1 = json.dumps(dict1)
print(r1)
print(type(r1))
#1.2
dict2 = dict(name="jack",age=10,score=100)
with open(r"data1.json","w",encoding="utf8") as f2:
json.dump(dict2,f2)
#2.读【反序列化】
"""
load():将文件中的json数据反序列化为对象
loads():将字符串的内容反序列化为Python对象
"""
#2.1
str1 = '{"name": "jack", "age": 10, "score": 100}'
r1 = json.loads(str1)
print(r1)
print(type(r1))
#2.2
with open(r"data1.json","r",encoding="utf8") as f2:
r2 = json.load(f2)
print(r2)
print(type(r2))
#练习:
#序列化
def jsonwrite(dict1):
with open(r"data2.json","w",encoding="utf8") as f1:
json.dump(dict1,f1)
print("数据保存成功!")
#反序列化
def jsonread():
with open(r"data2.json","r",encoding="utf8") as f2:
result = json.load(f2)
print(result)
if __name__ == "__main__":
mydict = {
"name":"狗蛋儿",
"age":18,
"qq":1736363,
"friends":['王大锤',"马化腾"],
"cars":[
{"brand":"polo","price":100000},
{"brand":"五菱宏光","price":50000},
{"brand":"qq","price":20000}
]
}
jsonwrite(mydict)
jsonread()
StringIO和BytesIO
数据的读写不一定只能在文件中操作,也可以在内存中操作,StringIO在内存中读写字符串,BytesIO在内存中读写字节,字节数据其实就是二进制数据
注意:StringIO和BytesIO是系统的类
from io import StringIO,BytesIO
#一、StringIO
#1.写入
#创建对象
si = StringIO()
#写入
#注意:将数据写入到了内存中
si.write("hello")
si.write("Python")
si.write("2141412")
#获取写入到内存中的数据
r1 = si.getvalue()
print(r1)
#2.读取
si2 = StringIO("hello\nPython\n2141412")
#全部读取
# r2 = si2.read()
# print(r2)
#按行读取
# r2 = si2.readline()
# print(r2)
while True:
r2 = si2.readline()
if r2 == "":
break
print(r2)
#二、BytesIO
#1.写入
bi = BytesIO()
#编码
# bi.write("中文fahjghahg".encode("utf-8"))
bi.write(bytes("中文fahjghahg",encoding="utf-8"))
print(bi.getvalue())
#2.读取
bi2 = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87fahjghahg')
r2 = bi2.read()
print(r2)
#解码
#print(r2.decode("utf-8"))
print(str(r2,encoding="utf-8"))
collections
1.namedtuple
#1.namedtuple
from collections import namedtuple
"""
tuple是一个有序的集合
其中允许存储重复元素,但是,一旦被定义之后,将不可改变
"""
#需求:使用元组表示一个二维坐标
#方式一
tuple1 = (2,4)
#方式二
class Point(object):
def __init__(self,x,y):
self.x = x
self.y = y
print(Point)
p = Point(2,4)
print(p.x,p.y)
p.x = 10
p.y = 20
print(p.x,p.y)
print("*" *20)
#方式三
#第一步:导入模块
#第二步:调用函数,定义了类
#namedtuple("名称",[属性])
Point = namedtuple("Point",["x","y"])
print(Point)
p = Point(2,4)
#第三步:访问属性
print(p.x,p.y)
# p.x = 10
# p.y = 20
# print(p.x,p.y)
"""
namedtuple是一个函数,它用来创建一个自定义的tuple对象
并且规定了tuple元素的个数,并可以用属性而不是索引访问元组中的元素
好处:可以很方便的定义一种新的数据类型,它具备元组的不可变性,又可以通过引用访问属性
"""
print(isinstance(p,Point))
print(isinstance(p,tuple))
Circle = namedtuple("Circle",['x','y','r'])
2.deque
from collections import deque
"""
使用list存储数据,按照索引访问元素速度较快,但是,插入和删除的速度较慢,因为list是线性存储
deque是为了实现高效的插入和删除操作的双向列表
添加元素
append:在末尾追加/appendleft:在头部添加
删除元素
pop:删除末尾元素/popleft:删除头部元素
"""
queue = deque([2,3,4])
print(queue)
#添加
queue.append(5)
print(queue)
queue.appendleft(6)
print(queue)
#删除
queue.pop()
print(queue)
queue.popleft()
print(queue)
3.defaultdict
from collections import defaultdict
"""
普通的dict,如果访问了一个不存在的key,则会报出异常KeyError
"""
dict1 = {"a":1,"b":2}
v1 = dict1["a"]
print(v1)
# v2 = dict1["c"]
# print(v2) #KeyError: 'c'
print(dict1)
#问题:如果key存在,则获取对应的value,但是如果key不存在,返回一个默认值,需要使用defaultdict
#defaultdict(有返回值的函数[,字典])
d = defaultdict(lambda : "aaaa")
print(d)
print(type(d))
#注意:和普通的dict相同,如果key不存在,dict[key] = value则表示将键值对添加到字典中
d["key1"] = 34
print(d)
#如果访问的key不存在,则默认获取的是函数的返回值
print(d["key2"])
4.OrderDict
from collections import OrderedDict
"""
字典:key是无序的
"""
#字典的写法
#1.无序字典
dict1 = {"a":1}
print(dict1)
dict2 = dict(x=1,y=3)
print(dict2)
dict3 = dict([("a",1),("b",2),("c",3)])
print(dict3)
#2.有序字典
dict4 = OrderedDict([("a",1),("b",2),("c",3)])
print(dict4)
#练习:
od = OrderedDict()
od["2"] = 20
od["1"] = 10
print(list(od.keys()))
5.Couter
from collections import Counter
#需求:统计一个单词中每个字符出现的次数
data = input("请输入文本:")
#方式一
dict1 = {}
for ch in data:
if ch not in dict1:
dict1[ch] = 1
else:
dict1[ch] += 1
print(dict1)
#方式二
#Counter是Collections中提供的一个计数器
c = Counter()
for ch in data:
c[ch] += 1
print(c)
print(type(c))
print(isinstance(c,Counter))
print(isinstance(c,dict))
#Counter实际上是dict的一个子类,专门用来统计可迭代对象个数
c = Counter()
for num in [2,3,43,43,3,3,3,3,22,100]:
c[num] += 1
print(c)