python pickle模組學習理解(二)
上一篇記錄pickle基本操作,這一篇學習研究那些型別是可以pickle的。引用
Python’s pickle (I’m talking standard Python 2.5/2.6/2.7 here) cannot pickle locks, file objects etc.
It also cannot pickle generators and lambda expressions (or any other anonymous code), because the pickle really only stores name references.
Python的pickle(我在這裡說的標準Python 2.5 / 2.6 / 2.7)不能pickle lock、file物件等。
它也不能pickle生成器和lambda表示式(或任何其他匿名程式碼),因為pickle只儲存名稱引用。
pickle只儲存名稱引用怎麼理解。我寫了下面的測試程式碼。這裡我在同一目錄編寫兩個檔案,一個用來儲存,一個用來讀取。
測試1目標測試函式,普通函式和帶有生成器(yield語句)的函式
測試在一個檔案讀
# coding: utf8 import pickle import pickle def storeTree(filename,*args): with open(filename,'wb') as fw: #開啟需要用'wb' for i in args: pickle.dump(i, fw,-1) #為了保護資料protocol=-1,設為0可以看到資料 def grabTree(filename): Mylist=[] #返回變數的列表 with open(filename,'rb') as fr: while True: #這裡用try最簡單,不用定義迴圈次數 try: Mylist.append(pickle.load(fr)) except: break return Mylist def TextPick(s,j): return("{}:{}".format(s,j)) def Tyield(i=None): if i is None: i=2 while 1: yield i i+=1 if __name__ == "__main__": filename = "pickT.txt" #測試函式 n = Tyield().__next__() # n=Tyield() #執行這句出現錯誤 # can't pickle generator objects 執行這句不能pickle generator物件 storeTree(filename,TextPick,n) #這裡n儲存的是一個整數 s=grabTree(filename) print("返回第一個是函式結果={}".format(s[0](2,3))) print("返回第二個是函式型別={}".format(type(s[1]))) print("返回第二個是函式結果={}".format(s[1]))
輸出:
返回第一個是函式結果=2:3
返回第二個是函式型別=<class ‘int’>
返回第二個是函式結果=2
第一個返回函式物件,第二個返回int物件執行完這個程式後我們看看其他程式呼叫
# coding: utf8 import pickle import pickle def grabTree(filename): Mylist=[] #返回變數的列表 with open(filename,'rb') as fr: while True: #這裡用try最簡單,不用定義迴圈次數 try: Mylist.append(pickle.load(fr)) except: break return Mylist def TextPick(s,j): return ("{}:{}".format(s, j)) if __name__ == "__main__": filename = "pickT.txt" b1=grabTree(filename)[0] print("返回第調函式{}".format(b1)) print("返回第調函式呼叫b1(2,3){}".format(b1(2,3)))
輸出:
返回第調函式<function TextPick at 0x01958078>
返回第調函式呼叫b1(2,3)2:3
這和我們的預期是一致的。不由考慮,如果讀取程式沒有定義TextPick怎摸樣 現在修改程式碼將TextPick改個名。執行
出現錯誤
File "D:/PYthonPro/CSV解析/量化序列化讀取.py", line 22, in <module>
b1=grabTree(filename)[0]
IndexError: list index out of range
list index out of 應該是查詢沒有找到函式名越界了。
其次如果我們修改函式內容會怎麼樣
將TextPick改為看看執行結果
def TextPick(s,j):
return s+j
返回第調函式<function TextPick at 0x01938078>
返回第調函式呼叫b1(2,3)5
所以得出結論pickle儲存函式實際上儲存的函式名
討論完函式再討論一下類,呼叫類名和函式是相似的,兩個程式必須有相同的類名,因為類有內部變數,所以需要測試一下
# coding: utf8
import pickle
import pickle
def storeTree(filename,*args):
with open(filename,'wb') as fw: #開啟需要用'wb'
for i in args:
pickle.dump(i, fw,-1) #為了保護資料protocol=-1,設為0可以看到資料
def grabTree(filename):
Mylist=[] #返回變數的列表
with open(filename,'rb') as fr:
while True: #這裡用try最簡單,不用定義迴圈次數
try:
Mylist.append(pickle.load(fr))
except:
break
return Mylist
class Person:
def __init__(self,n,a):
self.name=n
self.age=a
def show(self):
print("name={},age={}".format(self.name,self.age))
if __name__ == "__main__":
filename = "pickT.txt" #測試類和函式
_P=Person
aa = Person("JGood", 2)
print("第一次例項")
aa.show()
storeTree(filename,aa,_P)
s=grabTree(filename)
b0=s[0]
print("第二次例項")
b0.show()
b1 = s[1]
b1例項=b1("趙虎",12)
print("b1例項例項")
b1例項.show()
輸出:
第一次例項
name=JGood,age=2
第二次例項
name=JGood,age=2
b1例項例項
name=趙虎,age=12
我們在另一個檔案讀取一下儲存的資料
# coding: utf8
import pickle
import pickle
def grabTree(filename):
Mylist=[] #返回變數的列表
with open(filename,'rb') as fr:
while True: #這裡用try最簡單,不用定義迴圈次數
try:
Mylist.append(pickle.load(fr))
except:
break
return Mylist
class Person:
def __init__(self,n,a):
self.name=n
self.age=a
def show(self):
print("name={},age={}".format(self.name,self.age))
if __name__ == "__main__":
filename = "pickT.txt"
s = grabTree(filename)
b0 = s[0]
print("第二次例項")
b0.show()
b1 = s[1]
b1例項 = b1("趙虎", 12)
print("b1例項例項")
b1例項.show()
輸出:
第二次例項
name=JGood,age=2 看到內部變數保留了
b1例項例項
name=趙虎,age=12
# coding: utf8
import pickle
import pickle
def grabTree(filename):
Mylist=[] #返回變數的列表
with open(filename,'rb') as fr:
while True: #這裡用try最簡單,不用定義迴圈次數
try:
Mylist.append(pickle.load(fr))
except:
break
return Mylist
class Person:
def __init__(self,n,a):
self.name=n
self.age=a
self.oth="name={},age={}".format(self.name,self.age) #增加一個變數
def show(self):
print("name={},age={}".format(self.name,self.age))
if __name__ == "__main__":
filename = "pickT.txt"
s = grabTree(filename)
b0 = s[0]
print("b0的內部變數{}".format(b0.__dict__))
print("第二次例項")
b0.show()
b1 = s[1]
b1例項 = b1("趙虎", 12)
print(print("b1例項的內部變數{}".format(b1例項.__dict__)))
print("b1例項例項")
b1例項.show()
輸出:
b0的內部變數{‘name’: ‘JGood’, ‘age’: 2} 這裡有兩個變數
第二次例項
name=JGood,age=2
b1例項的內部變數{‘name’: ‘趙虎’, ‘age’: 12, ‘oth’: ‘name=趙虎,age=12’}
這裡有3個變數
None
b1例項例項
name=趙虎,age=12
從這裡可以看出 pickle只儲存名稱引用的含義