pickle在新舊版本python中的問題
阿新 • • 發佈:2018-11-03
在執行github上deep-siamese-text-similarity 的程式碼時, 遇到args[0] from __newobj__ args has the wrong class
的錯誤, 在一個issue裡找到了解決方法, 但是不知道為什麼, 遂做了一點小實驗做個驗證. 在此記錄.
python2.7
Python 2.7.15rc1 (default, Apr 15 2018, 21:51:34)
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> class A():
... def __init__():
... self.a = 5
...
>>> a = A()
>>> a.a
5
>>> class B(A):
... def __init__(self):
... self.b = 6
...
>>> b = B()
>>> b.b
6
>>> b.a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: B instance has no attribute 'a'
>>> class C(A):
... def __init__(self):
... sup = super(C, self)
... sup.__init__()
... self.c = 7
...
>>> c = C()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in __init__
TypeError: super() argument 1 must be type, not classobj
>>> # tips: `super` function can't be applied on old class
>>> class A_n(object):
... def __init__(self):
... self.a = 8
...
>>> class C(A_n):
... def __init__(self):
... sup = super(C, self)
... sup.__init__()
... self.c = 9
...
>>> c = C()
>>> c.a
8
>>> c.c
9
>>> class D(A_n):
... def __init__(self):
... self.sup = super(D, self)
... self.sup.__init__()
... self.d = 10
...
>>> d = D()
>>> d.a
8
>>> d.d
10
>>> import pickle
>>> pickle.dumps(c)
"ccopy_reg\n_reconstructor\np0\n(c__main__\nC\np1\nc__builtin__\nobject\np2\nNtp3\nRp4\n(dp5\nS'a'\np6\nI8\nsS'c'\np7\nI9\nsb."
>>> pickle.dumps(d)
"ccopy_reg\n_reconstructor\np0\n(c__main__\nD\np1\nc__builtin__\nobject\np2\nNtp3\nRp4\n(dp5\nS'a'\np6\nI8\nsS'd'\np7\nI10\nsS'sup'\np8\ng0\n(g1\ng2\nNtp9\nRp10\ng5\nbsb."
>>>
python3.x
Python 3.6.5 |Anaconda, Inc.| (default, Apr 29 2018, 16:14:56)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.4.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: class A():
...: def __init__(self):
...: self.a = 5
...:
In [2]: class B(A):
...: def __init__(self):
...: sup = super(B, self)
...: sup.__init__()
...: self.b = 6
...:
In [3]: a = A()
In [4]: a.a
Out[4]: 5
In [5]: b = B()
In [6]: b.a
Out[6]: 5
In [7]: class C(A):
...: def __init__(self):
...: self.sup = super(C, self)
...: self.sup.__init__()
...: self.c = 7
...:
In [8]: c = C()
In [9]: c.a
Out[9]: 5
In [10]: import pickle
In [11]: pickle.dumps(b)
Out[11]: b'\x80\x03c__main__\nB\nq\x00)\x81q\x01}q\x02(X\x01\x00\x00\x00aq\x03K\x05X\x01\x00\x00\x00bq\x04K\x06ub.'
In [12]: pickle.dumps(c)
---------------------------------------------------------------------------
PicklingError Traceback (most recent call last)
<ipython-input-12-4523793c002f> in <module>()
----> 1 pickle.dumps(c)
PicklingError: args[0] from __newobj__ args has the wrong class
新舊版本的python對比發現, 2.7版本中, 使用pickle序列化包含super物件的例項是沒有問題的, 但是在3.x版本中, 使用pickle序列化包含super物件的例項會報錯.