文章目錄
文件讀寫
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)