美文网首页
Python中使用pickle模块时变量地址改变问题

Python中使用pickle模块时变量地址改变问题

作者: 小新_XX | 来源:发表于2019-02-17 22:24 被阅读0次

    这是最近在使用pickle模块时发现的问题。将变量保存(dump)后再读取(load),读取后的变量地址会发生改变。具体例子如下:

    # 保存和读取数字变量
    x = 3.5
    print("id of x before dump:",id(x))
    with open('./x.pkl', 'wb') as f:
        pickle.dump(x, f)
    with open('./x.pkl', 'rb') as f:
        x = pickle.load(f)
    print("id of x  after load:",id(x))   
    

    运行输出为:

    id of x before dump: 2421413849584
    id of  x  after  load: 2421413849128

    这一性质对一般的变量使用影响不大。但在创建某个对象时,如果对象a的属性attr为另一个对象B(即a.attr = b),这时若对b执行pickle.dump()pickle.load()的操作,由于B的地址改变了,则A和B的所属关系也会消失。例子如下:

    class A:
        def __init__(self, attr = None):
            self.attr = attr
    class B:
        def __init__(self, value=2):
            self.value = value
    a = A()
    b = B()
    a.attr = b
    print("before dump:")
    print("a.attr.value:",a.attr.value)
    print("b.value:",b.value)
    

    运行输出为

    before dump:
    a.attr.value: 2
    b.value: 2

    此时若改变b.value的值, a.attr.value的值也会相应改变:

    #改变 b.value, 则a.attr.value也会相应改变
    b.value = -1
    print(b.value, a.attr.value)
    

    运行输出为

    -1 -1

    现对ab执行pickle.dump()pickle.load():

    a = A()
    b = B()
    a.attr = b
    with open('./b.pkl', 'wb') as f:
        pickle.dump(b, f)
    with open('./b.pkl', 'rb') as f:
        b = pickle.load(f)
    

    再改变b.value的值,结果如下:

    #改变 b.value, a.attr.value不变
    b.value = -1
    print(b.value, a.attr.value)
    

    输出结果为

    -1 2

    由以上测试可以看出,此时a.attr已经不再指向b。事实上,如果我们此时查看两者的地址,可以发现地址已经改变。

    print(id(b))
    print(id(a.attr))
    

    结果为:

    2421439794872
    2421439852784

    我在自己的程序中用了a.attr = b的结构,在dumpload后出现了这样的bug. 花了很久才找到问题所在。在网上也没有找到专门强调这一问题的文章,因此记录下来,以后写程序的时候要注意。

    相关文章

      网友评论

          本文标题:Python中使用pickle模块时变量地址改变问题

          本文链接:https://www.haomeiwen.com/subject/fdvneqtx.html