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只存储名称引用的含义

猜你喜欢

转载自blog.csdn.net/weixin_39462002/article/details/84106118