python其他知識目錄
1、一些對記憶體深入了解的案例
以下列舉清單,清單/字典/集合這些可變類型都是一樣的原理
變量是個位址,指向存儲資料的記憶體空間的位址,它的實質就相當于c語言裡的指針。變量和資料都存放在記憶體裡面
1.1記憶體相關的東西 指派和修改要差別開來,指派(重新定義)是重新開辟記憶體,修改是原記憶體空間内的改變
1.2修改清單元素的底層原理圖解
v1=[1,2,3]
v2=v1
v3=v1
v2,v3指向v1指向的位址,三者指向相同的位址。對變量做修改,修改的是同一個位址的值,三者都變化
代碼驗證:

>>> v1=[1,2,3]
>>> v2=v1
>>> v3=v1
>>> id(v1)
45927400
>>> id(v2)
45927400
>>> id(v3)
45927400
>>> v3[0]="mcw"
>>> print(v2)
['mcw', 2, 3]
View Code
1.3指派(重新定義)清單的記憶體位址變化圖解
v2=[1]
v2重新定義,記憶體位址改變

>>> v1=[1,2,3]
>>> v2=v1
>>> v3=v1
>>> v2=[1]
>>> id(v1)
46458520
>>> id(v3)
46458520
>>> id(v2)
46519160
>>> print(v2)
[1]
>>> id(v2[0]) #資料位址一緻
504310928
>>> id(v1[0])
504310928
>>> id(v3[0])
504310928
1.4 字元串.upper()等沒有修改原值
>>> v1="mcw" #v1指向一個位址
>>> v2=v1 #v2指向v1指向的位址
>>> v1.upper() #字元串無法修改,讓v1變大寫。v1.upper()後是開辟一個臨時記憶體存儲大寫的但是沒人接收,v1值沒有被修改
'MCW'
>>> print(v1,v2)
mcw mcw
>>> v1="mcw" #v1指向一個位址
>>> v2=v1 #v2指向v1指向的位址
>>> v3=v1.upper() #讓v1值變大寫後v3接收,但是v1值本身沒有被修改,
>>> print(v1,v2,v3)
mcw mcw MCW
1.6 清單.append(元素)等修改的是原值
v1=[1,2,3] #v1指向一個位址
v2=v1 #v2指向v1指向的位址
v1.append(v2) #清單可變,可修改,v1追加後v1改變,v2也改變,位址相同
print(v1,v2)

>>> v1=[1,2,3]
>>> v2=v1
>>> v1.append("mcw")
>>> print(v1,v2)
[1, 2, 3, 'mcw'] [1, 2, 3, 'mcw']
>>> id(v1)
46458880
>>> id(v2)
46458880
1.7清單中修改不可變元素代碼以及圖解
v1=[1,2,[3,4],5]
v2[0]="mcw"
v2[2][0]="xiaoma" #原v1[2][0]的值3,如果沒有東西指向它,那就是廢棄的垃圾,垃圾回收機制會将位址回收

>>> v1=[1,2,[3,4],5]
>>> v2=v1
>>> print(v1,v2)
[1, 2, [3, 4], 5] [1, 2, [3, 4], 5]
>>> v2[0]="mcw"
>>> print(v1,v2)
['mcw', 2, [3, 4], 5] ['mcw', 2, [3, 4], 5]
>>> id(v2[2][0])
504310960
>>> id(v2[2][1])
504310976
>>> id(v2[2])
46458800
>>> v2[2][0]="xiaoma"
>>> id(v2[2][0]) #v2[2][0]位址改變
46485536
>>> id(v2[2][1]) #v2[2][1]位址沒變
504310976
>>> id(v2[2]) #外層清單v2[2]位址沒發生改變,但是v2[2][0]的指向了另外一個新位址
46458800
>>> print(v1,v2)
['mcw', 2, ['xiaoma', 4], 5] ['mcw', 2, ['xiaoma', 4], 5]
1.8清單中修改可變元素代碼以及圖解
v2[2]=[2,4,6]
>>> v1=[1,2,[3,4],5]
>>> v2=v1
>>> id(v1[2]) #[3,4]
46458880
>>> id(v1[1]) # 2
504310944
>>> id(v1[2][1]) #4
504310976
>>>
>>> v2[2]=[2,4,6]
>>> id(v1[2]) #[1,4,6]
46563856
>>> id(v1[2][0]) #2
504310944
>>> id(v1[2][1]) #4
504310976
2、深拷貝,淺拷貝
可結合上面一些對記憶體深入了解的案例進行學習
2.1#str+int+bool拷貝都是這樣:
a="mcw"
b=copy.copy(a) #淺拷貝

>>> import copy
>>> a="mcw"
>>> b=copy.copy(a)
>>> c=copy.copy(a)
>>> id(a) is id(b)
False
>>> bool(a==b)
True
>>> id(a[0]) is id(b[0])
False
c=copt.deepcopy(a) #深拷貝

>>> import copy
>>> a="mcw"
>>> c=copy.deepcopy(a)
>>> id(a) is id(c)
False
>>> bool(a==c)
True
>>> id(a[0]) is id(c[0])
False
2.2、#list+set+dict的深淺拷貝
沒有嵌套的時候:
淺拷貝:拷貝記憶體位址,即變量名字 隻拷貝空殼
深拷貝:找到所有的可變類型資料(資料存放的記憶體空間)拷貝一份,不可變資料類型不拷貝,得到的結果一樣
有嵌套的時候:
淺拷貝:拷貝記憶體位址,即變量名字,拷貝空殼
深拷貝:找到所有的可變類型資料(資料存放的記憶體空間)拷貝一份,不可變資料類型不拷貝,得到的結果一樣。嵌套的把變化的拷貝,某層不變的就不拷貝
--------
應該每次都拷貝一份(但由于小資料池)
---------------------
帶疑問的總結:
淺拷貝:
隻拷貝第一層(疑問:拷貝清單,新的清單位址是不同的,但是新的清單裡清單元素無論是否
可變,都是指向原有元素的位址?隻拷貝第一層的位址指向 思考,那麼隻要是淺拷貝的值和位址都是
一樣的嗎,無論清單元素是否可變)(遇到元素無論是否可變都是拷貝的相同的指針)
深拷貝:
拷貝嵌套層次中的所有可變類型(疑問:拷貝清單,新的清單位址變了,内部不變的元素位址
指向原清單元素位址,但是可變的元素會再開辟新的記憶體位址(新的記憶體位址中的子元素如果不可變那
麼指向上層的元素的位址,新的記憶體位址中的子元素如果可變再開辟新的位址,将它本身放在新的位址
,但是子元素的子元素需要再次做判斷 #再次開辟的記憶體中不變的元素位址和原來還是相同?))(1
、遇到元素不可變的拷貝元素的指針,2、遇到不可變的就生成新的位址。3假如不可變的裡面還有元素
,對于這裡的元素繼續循環執行第一步和第二部的操作)
2.3深淺拷貝特殊情況:
元組裡面元素都是不可變的情況:
v1=(1,2,3,4)
淺:沒有換位址
深:沒有換位址
由于不可變類型,是以拷貝的時候不改變位址
元組裡面元素有可變的情況:
元組裡面有可變的,會把元組拷貝一下,元組改變了
v1=(1,2,[1,2,3],4)
淺:沒變
深:變了
3、檔案操作:
3.1檔案操作簡單介紹:
參考:http://www.runoob.com/python3/python3-file-methods.html
open() 方法
Python open() 方法用于打開一個檔案,并傳回檔案對象,在對檔案進行處理過程都需要使用到這個函數,如果該檔案無法被打開,會抛出 OSError。
注意:使用 open() 方法一定要保證關閉檔案對象,即調用 close() 方法。
open() 函數常用形式是接收兩個參數:檔案名(file)和模式(mode)。
open(file, mode='r')
完整的文法格式為:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
#建立空檔案,open使用w,a,w+,a+的方式可以建立。r,r+的方式不可以建立空檔案
參數說明:
- file: 必需,檔案路徑(相對或者絕對路徑)。
- mode: 可選,檔案打開模式
- buffering: 設定緩沖
- encoding: 一般使用utf8
- errors: 報錯級别
- newline: 區分換行符
- closefd: 傳入的file參數類型
- opener:
mode 參數有:
模式 | 描述 |
---|---|
t | 文本模式 (預設)。 |
x | 寫模式,建立一個檔案,如果該檔案已存在則會報錯。 |
b | 二進制模式。 |
+ | 打開一個檔案進行更新(可讀可寫)。 |
U | 通用換行模式(不推薦)。 |
r | 以隻讀方式打開檔案。檔案的指針将會放在檔案的開頭。這是預設模式。 |
rb | 以二進制格式打開一個檔案用于隻讀。檔案指針将會放在檔案的開頭。這是預設模式。一般用于非文本檔案如圖檔等。 |
r+ | 打開一個檔案用于讀寫。檔案指針将會放在檔案的開頭。 |
rb+ | 以二進制格式打開一個檔案用于讀寫。檔案指針将會放在檔案的開頭。一般用于非文本檔案如圖檔等。 |
w | 打開一個檔案隻用于寫入。如果該檔案已存在則打開檔案,并從開頭開始編輯,即原有内容會被删除。如果該檔案不存在,建立新檔案。 |
wb | 以二進制格式打開一個檔案隻用于寫入。如果該檔案已存在則打開檔案,并從開頭開始編輯,即原有内容會被删除。如果該檔案不存在,建立新檔案。一般用于非文本檔案如圖檔等。 |
w+ | 打開一個檔案用于讀寫。如果該檔案已存在則打開檔案,并從開頭開始編輯,即原有内容會被删除。如果該檔案不存在,建立新檔案。 |
wb+ | 以二進制格式打開一個檔案用于讀寫。如果該檔案已存在則打開檔案,并從開頭開始編輯,即原有内容會被删除。如果該檔案不存在,建立新檔案。一般用于非文本檔案如圖檔等。 |
a | 打開一個檔案用于追加。如果該檔案已存在,檔案指針将會放在檔案的結尾。也就是說,新的内容将會被寫入到已有内容之後。如果該檔案不存在,建立新檔案進行寫入。 |
ab | 以二進制格式打開一個檔案用于追加。如果該檔案已存在,檔案指針将會放在檔案的結尾。也就是說,新的内容将會被寫入到已有内容之後。如果該檔案不存在,建立新檔案進行寫入。 |
a+ | 打開一個檔案用于讀寫。如果該檔案已存在,檔案指針将會放在檔案的結尾。檔案打開時會是追加模式。如果該檔案不存在,建立新檔案用于讀寫。 |
ab+ | 以二進制格式打開一個檔案用于追加。如果該檔案已存在,檔案指針将會放在檔案的結尾。如果該檔案不存在,建立新檔案用于讀寫。 |
預設為文本模式,如果要以二進制模式打開,加上 b 。
3.2、隻讀:r 隻讀不能寫 檔案不存在報錯
utf-8的檔案,
# 打開檔案
file_object = open('log.txt',mode='r',encoding='utf-8') # 打開方式權限mode有r,read;
w,write; a,append; encoding
讀取内容:
變量=打開的檔案.read()
content = file_object.read()
print(content)
# 關閉檔案
file_object.close()
???open() 加載到記憶體,write 寫入資料到記憶體中,close将記憶體資料寫入磁盤????
使用範例:
1)
file_object = open('mcw.txt',mode='r',encoding='utf-8')
content = file_object.read()
print(content)
file_object.close()
---------------結果:
FileNotFoundError: [Errno 2] No such file or directory: 'mcw.txt'
問題原因:沒有這個檔案
解決辦法:在腳本的同一個目錄下建立檔案mcw.txt,并寫入内容:小馬過河測試。然後執行代碼
2)
file_object = open('mcw.txt',mode='r',encoding='utf-8')
content = file_object.read()
print(content)
file_object.close()
----------------結果:
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc2 in position 2: invalid
continuation byte
問題原因:Windows下手動建立的mcw.txt文本編碼格式為ANSI,
解決辦法:打開mcw.txt另存為utf-8格式的mcw.txt檔案
3)
file_object = open('mcw.txt',mode='r',encoding='utf-8')
content = file_object.read()
print(content)
file_object.close()
------------------結果:
小馬過河測試
機器内部似乎有個utf-8 unicode的轉換,疑問
3.3、隻寫:w 隻寫權限不能讀。檔案不存在則建立
file_object = open('log.txt',mode='w',encoding='utf-8') # r,read; w,write; a,append;#隻寫
打開的話,會先清空,再寫,需要小心。一般用于建立檔案
# 寫内容
變量=打開的檔案.write("")
# file_object.write('mcw')
打開的檔案.close()
使用範例:
1)
file_object = open('mcw.txt',mode='r',encoding='utf-8')
file_object.write('mcw')
file_object.close()
--------------結果:
file_object = open('mcw.txt',mode='r',encoding='utf-8')
FileNotFoundError: [Errno 2] No such file or directory: 'mcw.txt'
問題原因:沒有這個檔案
解決辦法:在腳本的同一個目錄下建立空檔案mcw.txt(utf-8格式的),然後執行代碼
2)
file_object = open('mcw.txt',mode='r',encoding='utf-8')
file_object.write('我是魔降風雲變')
file_object.close()
----------------結果:
file_object.write('我是魔降風雲變')
io.UnsupportedOperation: not writable
問題原因:我的mode是"r",不是"w"模式,
解決辦法:修改open的參數mode為需要的可寫模式
3)
file_object = open('mcw.txt',mode='w',encoding='utf-8')
file_object.write('我是魔降風雲變')
file_object.close()
-------------結果:
沒有輸出,沒有檔案。執行代碼後,在腳本目前目錄下建立檔案mcw.txt,并寫入“我是魔降風雲變”
4)
file_object = open('mcw.txt',mode='w',encoding='utf-8')
file_object.write('我是魔降風雲變')
file_object.close()
--------------結果:
沒有輸出,打開原本為空的mcw.txt文本,裡面出現内容我是魔降風雲變
python基礎知識-7-記憶體、深淺、檔案操作
5)
file_object = open('mcw.txt',mode='w',encoding='utf-8')
file_object.write('我是小馬過河')
file_object.close()
---------------結果:
沒有輸出,mcw.txt文本裡面的“我是魔降風雲變”原内容被新寫的“我是小馬過河”覆寫掉
python基礎知識-7-記憶體、深淺、檔案操作
6)
file_object = open('mcw.txt',mode='w',encoding='gbk')
file_object.write('我是mcw')
file_object.close()
-------------結果:
将上面的代碼改為encoding="gbk",在Windows上還是能覆寫掉原來的内容,打開也能正常的看,沒亂碼
顯示.
7、沒有讀的權限
file_object = open('mcw.txt',mode='w',encoding='utf-8')
file_object.read()
file_object.close()
--------------------------結果:
file_object.read()
io.UnsupportedOperation: not readable
8)
file_object = open('mcw.txt',mode='w',encoding='utf-8')
file_object.close()
--------------結果:
建立一個空檔案mcw.txt
3.4、 隻追加:a 不能讀 檔案不存在則建立
open("檔案路徑",mode="a",encoding="utf-8")
追加,在檔案後面添加内容
file_object = open('logfffff.txt',mode='a',encoding='utf-8') # r,read(隻讀); w,write(隻寫,
先清空,一般用于建立檔案); a,append;
file_object.write('你好')
使用範例:
1)
file_object = open('mcw.txt',mode='a',encoding='utf-8')
file_object.write('我喜歡吃米飯')
file_object.close()
---------------結果:
沒有列印輸出,沒有mcw.txt檔案。執行代碼後,自動在腳本目前目錄建立檔案mcw.txt,并寫入内容:
“我喜歡吃米飯”
python基礎知識-7-記憶體、深淺、檔案操作
2)
file_object = open('mcw.txt',mode='a',encoding='utf-8')
file_object.write(' 我叫小馬過河')
file_object.close()
---------------結果:
已有檔案mcw.txt,檔案内容為“我喜歡吃米飯”.執行代碼後,檔案内容為“我喜歡吃米飯 我叫小馬過
河”,追加了“ 我叫小馬過河”
python基礎知識-7-記憶體、深淺、檔案操作
3)a沒有可讀權限
file_object = open('mcw.txt',mode='a',encoding='utf-8')
file_object.write('我喜歡吃米飯')
file_object.read()
file_object.close()
-------------------結果:
file_object.read()
io.UnsupportedOperation: not readable
綜上:讀,檔案不存在會報錯,寫、追加檔案不存在都建立
3.4、可讀可寫: r+
讀:預設從0的光标開始讀,也可以通過seek調整光标的位置
寫:根據光标的位置,從目前光标位置開始進行寫入操作(可能會将其他的文字覆寫)
open("檔案路徑",mode="r+",encoding="utf-8")
先讀後寫,先寫後讀,讀前後有寫各是什麼情況呢
有一個标記,預設在最左邊。如果有值,往裡寫一個字元,覆寫标記後一個字元。
打開的檔案.seek(位元組),移動标記的。
先讀,讀完後光标會移到最後,然後再寫,不會影響文本已有的内容,相當于追加了
file_object = open('log.txt',mode='r+',encoding='utf-8')
1)# file_object.seek(2) # 調整光标的位置
file_object.write('浪')
# # 讀取内容
# content = file_object.read()
# print(content)
#
# file_object.write('666')
使用範例:
環境為:存在mcw.txt文檔,裡面内容為“我喜歡吃米飯 我叫小馬過河”,開頭沒有空格
1)
file_object = open('mcw.txt',mode='r+',encoding='utf-8')
file_object.seek()
content = file_object.read()
print(content)
--------------結果:
file_object.seek()
TypeError: seek() takes at least 1 argument (0 given)
問題原因:seek裡面要接參數,可以接參數“位元組”
2)
file_object = open('mcw.txt',mode='r+',encoding='utf-8')
file_object.seek(0)
content = file_object.read()
print(content)
----------------結果:
?我喜歡吃米飯 我叫小馬過河
備注:似乎seek接0的時候從開頭列印,列印出來的開頭貌似有點空格;
seek接3的時候從文本第一個字開始列印,
seek接6的時候,從“喜”開始往後列印
utf-8是三個位元組一個漢字
3)
file_object = open('mcw.txt',mode='r+',encoding='utf-8')
file_object.seek(0)
file_object.write('mcw')
content = file_object.read()
print(content)
file_object.close()
---------------結果:
原文檔mcw.txt的内容為“我喜歡吃米飯 我叫小馬過河”,列印輸出内容為“我喜歡吃米飯 我叫小馬過
河”,打開檔案檢視mcw.txt檔案内容為“mcw我喜歡吃米飯 我叫小馬過河”,開頭增加了寫入的内容“
mcw”。第二次隻列印内容不寫入,就會顯示出“mcw我喜歡吃米飯 我叫小馬過河”
python基礎知識-7-記憶體、深淺、檔案操作
4)
file_object = open('mcw.txt',mode='r+',encoding='utf-8')
file_object.seek(0)
content = file_object.read()
file_object.write('666')
print(content)
file_object.close()
----------------結果:
原文檔mcw.txt的内容為“mcw我喜歡吃米飯 我叫小馬過河”,列印輸出内容為“mcw我喜歡吃米飯 我叫
小馬過河”。打開檔案檢視在檔案結尾加了内容“mcw我喜歡吃米飯 我叫小馬過河666”
5)
file_object = open('mcw.txt',mode='r+',encoding='utf-8')
file_object.write('666')
content = file_object.read()
print(content)
file_object.close()
--------------結果:
這次沒有設定光标,原文檔内容“我喜歡吃米飯 我叫小馬過河”,寫入“666”後檢視檔案内容“666我
喜歡吃米飯 我叫小馬過河”
這次沒有設定光标,原文檔内容“我喜歡吃米飯 我叫小馬過河”,寫入“小馬”後檢視檔案内容“小馬
喜歡吃米飯 我叫小馬過河”
這次沒有設定光标,并且在上次操作後不是重新修改儲存的文檔,原文檔内容“小馬喜歡吃米飯 我叫小
馬過河”,寫入“,”後檢視檔案内容“,馬喜歡吃米飯 我叫小馬過河”
這次沒有設定光标,并且在上次操作後不是重新修改儲存的文檔,原文檔内容“,馬喜歡吃米飯 我叫小
馬過河”,寫入“ccccc”後檢視檔案内容“ccccc枩娆㈠悆绫抽キ 鎴戝彨灏忛┈杩囨渤”,亂碼了
這次沒有設定光标,原文檔内容“我喜歡吃米飯 我叫小馬過河”,寫入“ cc”後(cc前有個空格)檢視
檔案内容“ cc我喜歡吃米飯 我叫小馬過河”,沒有亂碼
6)
file_object = open('mcw.txt',mode='r+',encoding='utf-8')
file_object.seek(0)
file_object.write('小')
content = file_object.read()
print(content)
file_object.close()
---------------結果:
原檔案内容“我喜歡吃米飯 我叫小馬過河”,seek(0),寫入“小”後,檔案内容變為“小我喜歡吃米
飯 我叫小馬過河” pycharm列印輸出“我喜歡吃米飯 我叫小馬過河”
原檔案内容“我喜歡吃米飯 我叫小馬過河”,seek(0),寫入“小麗”後,檔案内容變為“小麗喜歡吃
米飯 我叫小馬過河” pycharm列印輸出“喜歡吃米飯 我叫小馬過河”
原檔案内容“我喜歡吃米飯 我叫小馬過河”,seek(0),寫入“你喜歡吃面條 你叫楊舟舟”後,檔案
内容變為“你喜歡吃面條 你叫楊舟舟過河”,pycharm列印輸出“過河”
原檔案内容“我喜歡吃米飯 我叫小馬過河”,seek(2),寫入“小小”後,檔案内容變為“锘灏忓皬滄
鍚冪背楗?鎴戝彨灏忛┈杩囨渤”,pycharm列印輸出“UnicodeDecodeError: 'utf-8' codec can't
decode byte 0x9c in position 0: invalid start byte”由于seek的位元組數不是3的倍數,也就是不是
一個utf-8漢字 3個位元組的倍數報錯。我是重新把檔案轉為utf-8操作才能重新用這個檔案的
原檔案内容“我喜歡吃米飯 我叫小馬過河”,seek(0),寫入“mm”後,檔案内容變為“mm挎垜鍠滄
鍚冪背楗?鎴戝彨灏忛┈杩囨渤”,pycharm列印輸出“UnicodeDecodeError: 'utf-8' codec can't
decode byte 0x9c in position 0: invalid start byte”由于寫入的位元組數不是3的倍數,也就是不是
一個utf-8漢字 3個位元組的倍數報錯。我是重新把檔案轉為utf-8操作才能重新用這個檔案的
原檔案内容“ cc我喜999吃米飯 我叫小馬過河”,seek(6),寫入“666”後,檔案内容變為“ cc我
666999吃米飯 我叫小馬過河”,覆寫了第6個位元組之後的三個位元組。 pycharm列印輸出“999吃米飯 我
叫小馬過河”
綜上:seek(位元組數)或寫入的位元組數不是3的倍數就會出現亂碼。Windows上和pycharm上操作,txt文本
前面有三個位元組的空内容,可以寫入内容,如果寫入的大于3個位元組的内容,就會開始覆寫第一個中文字
符。如果是代碼操作後沒有手動粘貼儲存文檔的話,重新對檔案操作,開頭沒有那3個位元組了。如果寫入
的不夠3的倍數,加空格補充到3的倍數不會亂碼。seek(位元組數),再寫入,會從位元組數之後開始覆寫。
不用seek,預設從頭開始覆寫.
3.5、w+寫讀: w+ 不同于讀寫
讀:預設光标永遠在寫入的最後或0,也可以通過 seek 調整光标的位置。
寫:寫入時會将檔案清空,讀取時需要調整光标到想讀的位置(光标預設在最後,到開頭seek(0))
open("檔案路徑",mode="w+",encoding="utf-8")
file_object = open('mcw.txt',mode='w+',encoding='utf-8')
data = file_object.read()
print(data)
file_object.write('小馬過河')
file_object.seek(0)
實驗案例:
1)
file_object = open('mcw.txt',mode='w+',encoding='utf-8')
data = file_object.read()
print(data)
------------------結果:
mcw.txt中有内容,執行代碼之後情況,沒有讀出内容,即使在讀之前添加seek也不行。執行寫入時會将檔案清空
2)
file_object = open('mcw.txt',mode='w+',encoding='utf-8')
file_object.write("魔降風雲變")
data = file_object.read()
print(data)
------------------結果:
mcw.txt中有内容“小馬過河”,多次執行代碼都是寫入了“魔降風雲變”,并将之前的已有的内容清空了。pycharm沒有列印出内容。
python基礎知識-7-記憶體、深淺、檔案操作
3)
file_object = open('mcw.txt',mode='w+',encoding='utf-8')
file_object.write("小馬過河")
file_object.seek(6)
data = file_object.read()
print(data)
file_object.close()
----------------------結果:
mcw.txt中有内容“魔降風雲變”,多次執行代碼都是寫入了“小馬過河”,寫完後seek(6),讀取到第6個位元組之後的内容“過河”并在pycharm列印出來。,每次執行都将之前已有的内容清空了。
3.6、a+
- 讀:預設光标在最後,也可以通過 seek 調整光标的位置。然後再去讀取。
- 寫:永遠寫到最後。
pen("檔案路徑",mode="a+",encoding="utf-8")
光标預設放在最後。想讀先要移動光标到開頭)(seek(0))。a+ 不存在修改,不會在光标處往後覆寫.隻要一寫,無論光标在哪裡都會立即跳到
最後然後進行追加内容。
檔案打開方式
file_object = open('mcw.txt',mode='a+',encoding='utf-8')
# file_object.seek(0)
# data = file_object.read()
# print(data)
file_object.write('666')
實驗案例:
1)
file_object = open('mcw.txt',mode='a+',encoding='utf-8')
file_object.write("小馬過河")
file_object.close()
-------------結果:
mcw.txt檔案不存在就會建立,并寫入内容“小馬過河”
2)
file_object = open('mcw.txt',mode='a+',encoding='utf-8')
file_object.seek(0)
data = file_object.read()
print(data)
-----------------結果:
如果沒有file_object.seek(0),光标預設在最後,沒有讀出内容。設定光标在開頭才讀出了内容,注意:讀内容需要有變量去接收内容并将它列印,才能顯示出來
3)
file_object = open('mcw.txt',mode='a+',encoding='utf-8')
file_object.write("下午,你好呀!")
file_object.seek(0)
data=file_object.read()
print(data)
-----------------結果:
原檔案内容為“小馬過河”,執行後,檔案後面追加了“下午,你好呀”,檔案内容變為“小馬過河下午,你好呀!”,pycharm列印輸出“小馬過河下午,你好呀!”
python基礎知識-7-記憶體、深淺、檔案操作
4)
file_object = open('mcw.txt',mode='a+',encoding='utf-8')
file_object.seek(0)
file_object.write("我很好")
file_object.close()
--------------結果:
後面追加内容了。即使光标移到最前面,隻要一寫,無論光标在哪裡都會立即跳到最後然後進行追加内容。試驗表明,追加之後光标在最後需要重新seek調整,不然讀不到内容。
python基礎知識-7-記憶體、深淺、檔案操作
小點: r** w** a* r+ w+ a+ 使用頻率
讀取檔案内容到記憶體,在記憶體中修改,點選儲存才會重新将修改的内容寫入磁盤 打開的檔案.read(字元個數,預設為所有似乎)
3.7、檔案讀操作:
檔案讀操作:
設定光标位置,往後讀取幾個字元
file_object = open('mcw.txt',mode='r',encoding='utf-8')
1)讀取檔案的所有内容到記憶體。
如果檔案大于記憶體,那麼記憶體裝不下全部内容。是以如果以後讀取一個特别大的檔案,那就一點一點的
讀
file_object = open('mcw.txt',mode='r',encoding='utf-8')
data = file_object.read()
print(data)
file_object.close()
--------------結果:
read要有變量接收并列印
python基礎知識-7-記憶體、深淺、檔案操作
2)# 讀取檔案的所有内容到記憶體,并按照每一行進行分割到清單中。#可對每行去掉\n,在做操作
# data_list = file_object.readlines()
# print(data_list)
file_object = open('mcw.txt',mode='r',encoding='utf-8')
data_list = file_object.readlines()
print(data_list)
file_object.close()
---------------結果:
['\ufeff我叫小馬過河\n', '我來自虛空深處。\n', '我來了,可是地球人說,魔降風雲變。']
with open("mcw.txt",mode="r",encoding="utf-8") as f:
content = f.read()
row_list=content.split("\n") #将檔案都讀出來,然後去掉每行的換行符形成的清單
print(row_list)
--------------------結果:
['\ufeff我叫小馬過河', '明天,你好']
3)指定單詞讀取檔案的字元個數,連續讀取出來
start=0
whle True:用
date=對象.read(字元個數) #很少
file_object = open('mcw.txt',mode='r',encoding='utf-8')
while True:
data=file_object.read(2)
print(data)
-----------結果:
檔案内容死循環從裡面每次列印兩個字元的大小。檔案内容循環結束,列印空的内容
4)# 指定讀取目前光标所在的位置後的字元個數
# data = file_object.read(4)
file_object = open('mcw.txt',mode='r',encoding='utf-8')
data = file_object.read(4)
print(data)
file_object.close()
----------結果:
”列印出“我叫小”,由于開頭有一個特殊字元,是以顯示少了一個
5)# 如果以後讀取一個特别大的檔案 (用的最多)
如果有換行符号\n,也可以用strip去符号
方法一:
for 變量line in 打開的檔案:
line=line.strip()
# for line in file_object:
# line = line.strip()
# print(line)
# file_object.close()
file_object = open('mcw.txt',mode='r',encoding='utf-8')
for line in file_object:
line=line.strip()
print(line)
file_object.close()
----------------結果:
我叫小馬過河
我來自虛空深處。
我來了,可是地球人說,魔降風雲變。
或者:
file_object = open('mcw.txt',mode='r',encoding='utf-8')
data_list = file_object.readlines()
print(data_list)
file_object.close()
-----------結果:
['\ufeff我叫小馬過河\n', '我來自虛空深處。\n', '我來了,可是地球人說,魔降風雲變。']
strip去掉\n的換行符
li=[]
file_object = open('mcw.txt',mode='r',encoding='utf-8')
data_list = file_object.readlines()
for i in data_list:
li.append(i.strip())
print(li)
file_object.close()
-------------------結果:
['\ufeff我叫小馬過河', '我來自虛空深處。', '我來了,可是地球人說,魔降風雲變。']
3.8、檔案寫操作:
open("檔案路徑",mode="w",encoding="utf-8")
寫,往後寫,換行\n。寫完要關閉,寫的在記憶體,當關閉的時候強制刷到硬碟裡面
file_object = open('mcw.txt',mode='w',encoding='utf-8')
file_object.write('asdfadsfasdf\n')
file_object.write('asdfasdfasdfsadf')
file_object = open('mcw.txt',mode='w',encoding='utf-8')
file_object.write('abc\ndef')
file_object.close()
-----------結果:
覆寫了之前的内容。\n換行符生效,起到換行作用
3.9将多個windows目錄下的檔案内容統一寫到一個檔案,并增加檔案名字分隔開來
import os
from datetime import datetime
basedir="D:\BaiduNetdiskDownload\XXX從入門到精通PPT\課本源代碼"
bb=os.walk(basedir)
for a,b,c in bb:
for i in c:
filep=os.path.join(a,i)
li=[]
with open(filep,mode="rb") as f:
for line in f:
li.append(line)
with open('mcw.txt', mode="ab") as f:
# f.write(("\n----------------------------開始-%s------------------------------\n"%i).encode("gbk"))
f.write('\r\n'.encode())
f.write('\r\n'.encode())
f.write('\r\n'.encode())
f.write(("-------開始-%s----收集by小馬過河-----"%i).encode("gbk"))
f.write('\r\n'.encode())
f.write('\r\n'.encode())
# f.write(('\n--------------------------------------------------------------\n').encode("gbk"))
for j in li:
f.write(j)
f.write('\r\n'.encode())
f.write(("-------結束-%s----收集by魔降風雲變-----"%i).encode("gbk"))
f.write(datetime.now().strftime("%Y_%m_%d %H:%M:%S").encode('gbk'))
f.write('\r\n'.encode())
print(filep)
注意點:
1)rb讀取,ab追加。Windows裡追加用gbk不會亂碼。
2)這裡加入\n不換行,加入\r\n才換行
3.10、使用seek定位行内容的案例
# 1.有一個檔案,這個檔案中有20000行資料,開啟一個線程池,為每100行建立一個任務,列印這100行資料。
# import time
# from threading import Thread
# from concurrent.futures import ThreadPoolExecutor
#
# # with open('mcw.txt',mode="a",encoding="utf-8") as f :
# # for i in range(0,20000):
# # f.write("魔降風雲變-%s\n"%i)
# shang=int(20000/100)
# li=[]
# with open('mcw.txt',mode="r",encoding="utf-8") as f :
# for line in f:
# line=line.strip()
# li.append(line)
# index_li=[]
# for i in range(shang):
# start_index=i*100
# end_index=(i+1)*100
# index=(start_index,end_index)
# index_li.append(index)
# def func(li,index):
# print("\n".join(li[index[0]:index[1]]))
# tp=ThreadPoolExecutor(10)
# for i in index_li:
# t=Thread(target=func,args=(li,i,))
# t.start()
# tp.shutdown()
# 方法二:
import time
from threading import Thread
from concurrent.futures import ThreadPoolExecutor
# with open('mcw.txt',mode="a",encoding="utf-8") as f :
# for i in range(0,20000):
# f.write("魔降風雲變-%s\n"%i)
num_li=[i for i in range(0,20001,100)]#[0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000]
cur_li=[]
with open('mcw.txt',mode="rb") as f :
for i in range(0,20000): #i是0的時候還沒讀取遊标是0,i是第100行(這行還沒讀取)的時候遊标是1990,
if i in num_li:
cur=[i,f.tell()]
cur_li.append(cur)
print(f.tell())
data = f.readline()#.strip()
# data=f.readlines()
# print(data)
print(cur_li) #[[0, 0], [100, 1990], [200, 4090], [300, 6190], [400, 8290], [500, 10390], [600, 12490], [1800, 38490], [1900, 40690]]
cur_li_new=[ {"第幾行到第幾行:":"%s到%s行:"%(cur_li[i][0],cur_li[i+1][0]),"seek起始位置:":cur_li[i][1],"read讀取位元組:":cur_li[i+1][1]-cur_li[i][1]} for i in range(len(cur_li)) if i<len(cur_li)-1] #,cur_li[i+1][1]-cur_li[i][0]-1):
cur_li_new.append({"第幾行到第幾行:":"%s到%s行:"%(cur_li[-1][0],cur_li[-1][0]+100),"seek起始位置:":cur_li[-1][1],"read讀取位元組:":None})
print(cur_li_new)
def func(i):
print("-----------%s開始讀取----------------" % i['第幾行到第幾行:'])
f.seek(i['seek起始位置:'])
data = f.read(i['read讀取位元組:'])
print(data.decode())
time.sleep(0.1)
print("-----------%s已經結束----------------" % i['第幾行到第幾行:'])
start=time.time()
with open('mcw.txt',mode="rb") as f :
# tp=ThreadPoolExecutor(10)
for i in cur_li_new: #單個i元素:{'第一行到第幾行:': '0到100行:', 'seek起始位置:': 0, 'read讀取位元組:': 1990} {'第一行到第幾行:': '100到200行:', 'seek起始位置:': 1990, 'read讀取位元組:': 2100}, {'第一行到第幾行:': '200到300行:', 'seek起始位置:': 4090, 'read讀取位元組:': 2100},
func(i)
# Thread(target=func, args=(i,)).start()
# tp.shutdown()
print(time.time()-start)
# [200, 4090], [300, 6190] seek到4090,read(6190-4090)
#1[0, 0],2 [100, 1990],3 [200, 4090],4 [300, 6190]
# ---------------
#0.0500028133392334 函數執行
#20.00814437866211 線程池執行
#由上可知,實作了線程池效果
seek定位原理:
1)讀取第三行,條件一是:需要seek到第三行第一個位元組之前,這個位元組數為第三行之前的位元組總數,即第一第二行的位元組總數,條件二是:我需要讀取的第三行位元組數量
2)我for循環讀取行數,每次循環f.tell()獲得位元組大小,即讀到第二行獲得第二行之前總的位元組數,讀完第三行獲得第三行及之前的位元組數。由此獲得了條件一
3)我用前三行的位元組數減去前兩行的位元組數獲得條件2
4)readline()讀行 tell()擷取讀取了多少位元組 read(位元組數) seek(位元組數)
注意點:rb讀 保持正确的位元組數。
3.11、tell()擷取第一行位元組數,然後從開頭read這個位元組數擷取内容超過一行的問題
with open('mcw.txt',mode="r",encoding="utf-8") as f :
# data = f.readline()
# print(data)
# print(f.tell())
# -----結果:
# 魔降風雲變-0
#
# 19
# 要點一(問題):
# f.seek(0)
# data = f.read(19)
# print(data)
# print(f.tell())
# -------------------結果:
# 魔降風雲變-0
# 魔降風雲變-1
# 魔降風
# 47
# 試了試兩段代碼,第一段代碼是讀取檔案第一行得到第一行總共19個位元組,
# 然後我seek(0),f.read(19)
# 往後讀取19個位元組,預期隻讀取到第一行
# 結果和預期隻列印第一行不同,多列印了47 - 19 = 28
# 個位元組,這是什麼原因呢?
# 是read有問題麼?怎麼看都不想說隻讀取了,難道是編碼問題
# 解答:編碼問題,rb讀取就可以了,想列印就資料.decode()
with open('mcw.txt',mode="rb") as f
3.12、f.read(None)
# 要點二:
# f.read(None)從目前指針位置讀取檔案内容到最後