一、小數據池 1. 小數據池定義 小數據池(常量池),一種數據緩存機制,也被稱為駐留機制。小數據池只針對: 整數、字元串、布爾值 。其他數據類型不存在駐留機制。 2. 各類型數據池限定 (1) 整型 在python中 5 ~ 256 之間的整數會被駐留在記憶體中。每次使用都是同一個對象。 (2) 字元 ...
一、小數據池
1. 小數據池定義
小數據池(常量池),一種數據緩存機制,也被稱為駐留機制。小數據池只針對:整數、字元串、布爾值。其他數據類型不存在駐留機制。
2. 各類型數據池限定
(1) 整型
在python中 -5 ~ 256 之間的整數會被駐留在記憶體中。每次使用都是同一個對象。
(2) 字元串
將一定規則的字元串緩存。在使用的時候,記憶體中只會創建一個該數據的對象。保存在小數據池中。當使用的時候直接從小數據池中獲取對象的記憶體應用。而不需要創建一個新的數據,這樣會節省更多的記憶體區域。
優點:能提高一些字元串,整數的處理速度。省略創建對象的過程
缺點:在“池”中創建或插入新的內容會花費更多的時間
a. 如果字元串的長度是0或者1, 都會預設進行緩存
b. 字元串長度大於1, 但是字元串中只包含字母, 數字, 下劃線時才會緩存
c. 用乘法得到的字元串.
①. 乘數為1, 僅包含數字, 字母, 下劃線時會被緩存. 如果包含其他字元, 而長度<=1 也會被駐存,
②. 乘數大於1 . 僅包含數字, 字母, 下劃 線這個時候會被緩存. 但字元串長度不能大於20
d. 指定駐留留. 我們可以通過sys模塊中的intern()函數來指定要駐留留的內容.
>>> from sys import intern
>>> a = intern('alex.sb.com' * 10)
>>> b = intern('alex.sb.com' * 10)
>>> a is b
True
3. py文件與command小數據池區別
在代碼塊內的緩存機制是不一樣的. 在執行同一個代碼塊的初始化對象的命令時, 會檢查其值是否已經存在, 如果存在, 會將其重用. 換句話說: 執行同一個代碼塊時, 遇到初始 化對象的命令時,他會將初始化的這個變數與 值存儲在一個字典中, 在遇到新的變數時, 會先在字典中查詢記錄, 如果有同樣的記錄那麼它會重覆使用這個字典中的之前的這個值. 所以在 你給出的例子中, 文件執行時(同一個代碼塊) 會把a, b兩個變數指向同一個對象. 如 果是不同的代碼塊, 他就會看這個兩個變數是否是滿足小數據池的數據, 如果是滿足小數據池的數據則會指向同一個地址. 所以: a, b的賦值語句分別被當作兩個代碼塊執行, 但是他們不滿足小數據池的數據所以會得到兩個不同的對象, 因而is判斷返回False.
py文件里. 一個代碼塊內部. 只會緩存int, str, bool 也有自己的小數據池。 緩存的範圍會比外面的代碼塊的數據池要大
(1). 數字。都會緩存。 運算的結果不緩存(-5~256 會緩存)
(2). 字元串。 預設的字元串都緩存. 如果有乘法。 遵循上方的結論
(3). 布爾值。 預設緩存
4. is 和 == 區別
查看記憶體地址:id(變數)
is : 判斷左右兩端內容的記憶體地址是否一致. 如果返回True, 那可以確定這兩個變數量使 用的是同一個對象
== :判斷左右兩端的值是否相等. 是不是一致.
二、編碼
1. python2和python編碼
(1) python2 - ASCII
預設使用ASCII碼,所以不支持中文. 如果需要在Python2中更改編碼. 需要在文件的開始編寫。
# -- encoding:utf-8 -
(2) python3 - UTF-8
(1)ASCII : 最早的編碼.裡面有英文大寫字母,小寫字母,數字,一些特殊字元.沒有中文,8個01代碼,8b,1B (2)GBK: 中文國標碼,裡面包含了ASCII編碼和中文常用編碼.16b, 2B
(3)UNICODE: 萬國碼, 里麵包含了全世界所有國家文字的編碼. 32b, 4B, 包含了了 ASCII
(4)UTF-8: 可變長度的萬國碼.是unicode的一種實現.最⼩字元占8位;
英文8b,1B 歐文16b,2B 中文24bit,3B
綜上, 除了了ASCII碼以外, 其他信息不能直接轉換.
2. 編解碼
在python3的記憶體中。 在程式運⾏階段。 使用的是unicode編碼。 因為unicode是萬國碼。 什麼內容都可以進行顯示。 那麼在數據傳輸和存儲的時候由於unicode比較浪費空間和資源。 需要把 unicode轉存成UTF-8或者GBK 進行存儲。 怎麼轉換呢。 在python中可以把文字信息進行編碼。 編碼之後的內容就可以進行傳輸了。 編碼之後的數據是bytes類型的數據。其實啊。 還是原來的數據只是經過編碼之後表現形式發生了改變而已。
bytes的表現形式: (1)英⽂ b'alex' 英⽂的表現形式和字元串沒什麽兩樣 (2)中文 b'\xe4\xb8\xad' 這是一個漢字的UTF-8的bytes表現形式
(1) 舉例
s = "alex"
print(s.encode("utf-8")) # 將字元串串編碼成UTF-8
print(s.encode("GBK")) # 將字元串串編碼成GBK
結果:
b'alex'
b'alex'
s = "中"
print(s.encode("UTF-8")) # 中?文編碼成UTF-8
print(s.encode("GBK")) # 中?文編碼成GBK
結果:
b'\xe4\xb8\xad'
b'\xd6\xd0
備註:英⽂編碼之後的結果和源字元串一致.中文編碼之後的結果根據編碼的不同. 編碼結果也不同. 我們能看到. 一個中文的UTF-8編碼是3個位元組. 一個GBK的中文編碼是2個位元組. 編碼之後的類型就是bytes類型.在網路傳輸和存儲的時候我們python是保存和存儲的bytes 類型. 那麼在對方接收的時候. 也是接收的bytes類型的數據. 我們可以使用decode()來進行解碼操作. 把bytes類型的數據還原回我們熟悉的字元串
s = "我叫李李嘉誠"
print(s.encode("utf-8"))
# b'\xe6\x88\x91\xe5\x8f\xab\xe6\x9d\x8e\xe5\x98\x89\xe8\xaf\x9a'
# 解碼
print(b'\xe6\x88\x91\xe5\x8f\xab\xe6\x9d\x8e\xe5\x98\x89\xe8\xaf\x9a'.decod e("utf-8"))
s = "我是文字"
bs = s.encode("GBK") # 我們這樣可以獲取到GBK的文字
# 把GBK轉換成UTF-8
# 首先要把GBK轉換成unicode. 也就是需要解碼
s = bs.decode("GBK") # 解碼
# 然後需要進行重新編碼成UTF-8
bss = s.encode("UTF-8") # 重新編碼
print(bss)
三、文件操作
1. 初始文件操作
使用python來讀寫文件時非常簡單的操作。我們使用open()函數來打開一個文件,獲取文件句柄,然後通過文件句柄就可以進行各種文件操作。打開文件需要close()文件。可使用with上下文進行操作文件。
2. 文件操作模式
文件操作流程:建立文件對象,調用文件方法進行操作,不要忘記關閉文件(文件不關閉的情況下,內容會放在緩存,雖然python會在最後自動把內容讀到磁碟)
(1) r(only-read)
f = open("file", "r")
# read逐個字元地全部讀取出,read可以指定參數,設定要讀取多少字元;無論一個英文字母還是一個漢字都是一個字元
f_read = f.read()
f = open('file1','r')
# readlines會把內容以列表的形式輸出
f_read = f.readlines()
print(f_read)
f.close()
# 推薦讀取方式
#輸出一行內容輸出一個空行,一行內容一行空格... 因為文件中每行內容後面都有一個換行符,而且print()語句本身就可以換行,如果不想輸出空行,就需要使用下麵的語句:print(line.strip())
f = open('file1','r')
for line in f.readlines()
print(line)
f.close()
# 讀取圖片、視頻流文件 - rb
f = open('file', rb)
(2) w(only-write)
在進行操作前,文件中所有內容會被清空。由於Python3的預設編碼方式是Unicode,所以在寫入文件的時候需要調用utf8,以utf8的方式保存,這時pycharm(預設編碼方式是utf8)才能正確讀取,當讀取文件時,文件是utf8格式,pycharm也是utf8,就不需要調用了。寫入位元組文件wb
f = open('file1','w',encoding='utf8')
f_w = f.write('hello world')
#有意思的是,這裡並不列印'hello world',只列印寫入多少字元
print(f_w)
f.close()
(3) a(append)
與w模式不同的是,a模式不會把原來內容清空,而是游標移到內容最後位置,繼續寫入新內容。比如在最後追加'hello world'
f = open('file1','a')
f_a = f.write('hello world')
#還是會列印寫入的字元數
print(f_a)
f.close()
(4) 讀取大文件
num = 0
# 不要過早關閉文件,否則程式不能識別操作句柄f.
f.close()
f = open('file','r')
# for內部把f變為一個迭代器,用一行取一行
for i in f:
num += 1
if num == 5:
i = ''.join([i.strip(),'hello world'])
print(i.strip())
f.close()
3. 其他操作
(1) tell 和 seek
f = open('file','r')
print(f.tell()) #游標預設在起始位置
f.seek(10) #把游標定位到第10個字元之後
print(f.tell()) #輸出10
f.close()
----------------------
f = open('file','w')
print(f.tell()) #先清空內容,游標回到0位置
f.seek(10)
print(f.tell())
f.close()
----------------------
f = open('file','a')
print(f.tell()) #游標預設在最後位置
f.write('你好 世界')
print(f.tell()) #游標向後9個字元,仍在最後位置
f.close()
(2) flush
同步將數據從緩存轉移到磁碟; 如實現進度條
import sys,time #導入sys和time模塊
for i in range(40):
sys.stdout.write('*')
# flush的作用相當於照相,拍一張沖洗一張
sys.stdout.flush()
time.sleep(0.2)
# 下麵代碼也能夠實現相同的功能
import time
for i in range(40):
# print中的flush參數
print('*',end='',flush=True)
time.sleep(0.2)
(3) truncate - 截斷
不能是r模式下執行,w模式下,已經清空所有數據,使用truncate
沒有任何意義,a模式下,截斷指定位置後的內容。
f = open('file','a')
# 只顯示6個位元組的內容(6個英文字元或三個漢字),後面的內容被清空
f.truncate(6)
(4) 游標位置總結
#--------------------------游標總結head-----------------------------------
f = open('file','r')
print(f.read(6)) #6個字元
print(f.tell()) #位置12位元組,一個漢字兩個位元組
f.close()
f = open('file','r')
f.seek(6) #6個位元組
print(f.tell())
f.close()
f = open('file','a')
# 游標預設在最後位置
print(f.tell())
f.write('你好 世界')
# 游標向後9個位元組,一個漢字兩個位元組,仍在最後位置 182-->191
print(f.tell())
f.close()
f = open('file','a',encoding='utf-8')
# 由於需要游標定位位置,所以也是位元組。只顯示6個位元組的內容(6個英文字母或三個漢字,一個漢字兩個位元組),後面的內容被清空。
print(f.truncate(6))
f.close()
(4) r+/w+/a+
r+:讀寫模式,游標預設在起始位置,當需要寫入的時候,游標自動移到最後
w+:寫讀模式,先清空原內容,再寫入,也能夠讀取
a+:追加讀模式,游標預設在最後位置,直接寫入,也能夠讀取。
f = open('file','a')
print(f.tell()) #末尾207位置
f.close()
f = open('file','r+')
print(f.tell()) #0位置
print(f.readline()) #讀取第一行
f.write('羊小羚') #游標移到末尾207位置並寫入
print(f.tell()) #213位置
f.seek(0) #游標移到0位置
print(f.readline()) #讀取第一行
f.close()
(5) 修改文件內容
由於數據存儲機制的關係,我們只能把文件1中的內容讀取出來,經過修改後,放到文件2中
f2 = open('file2','w',encoding='utf8') #寫入的時候必須加utf8
f1 = open('file','r')
num = 0
for line in f1: #迭代器
num += 1
if num == 5:
line = ''.join([line.strip(),'羊小羚\n']) #裡面就是對字元串進行操作了
f2.write(line)
f1.close()
f2.close()
4. with語句
可以同時對多個文件同時操作,當with
代碼塊執行完畢時,會自動關閉文件釋放記憶體資源,不用特意加f.close()
,我們通過下麵的示例體會with
的用法和好處。用with
語句重寫8中的代碼
num = 0
with open('file','r') as f1,open('file2','w',encoding='utf8') as f2:
for line in f1:
num += 1
if num == 5:
line = ''.join([line.strip(),'羊小羚'])
f2.write(line)