Class attributes changes at load if the object is in a list or tuple.
Closed this issue · 1 comments
I created a simple test code like the following. I expect the a
in unpickled B
objects (b1
, b2
, l1[0]
, l2[0]
) should have the same value as the a
in the original B
object (b
).
import dill
class A:
pass
class B:
a = A()
def get_value(self):
return self.a
b = B()
print(f'b: {b.get_value()}')
pickled_b = dill.dumps(b)
b1 = dill.loads(pickled_b)
print(f'b1: {b1.get_value()}')
b2 = dill.loads(pickled_b)
print(f'b2: {b2.get_value()}')
####
l = [B()]
print(f'l[0]: {l[0].get_value()}')
pickled_l = dill.dumps(l)
l1 = dill.loads(pickled_l)
print(f'l1[0]: {l1[0].get_value()}')
l2 = dill.loads(pickled_l)
print(f'l2[0]: {l2[0].get_value()}')
But, it worked as expected when dumping with the object directly, but not when dumping a list including the object. See below. Is this an intended behavior?
baeminbo$ python --version
Python 3.11.4
baeminbo$ pip list
Package Version
---------- -------
dill 0.3.7
pip 23.1.2
setuptools 65.5.0
[notice] A new release of pip is available: 23.1.2 -> 23.3
[notice] To update, run: pip install --upgrade pip
baeminbo$ python dilltest.py
b: <__main__.A object at 0x108d04d90>
b1: <__main__.A object at 0x108d04d90>
b2: <__main__.A object at 0x108d04d90>
l[0]: <__main__.A object at 0x108d04d90>
l1[0]: <__main__.A object at 0x1093e3150>
l2[0]: <__main__.A object at 0x1093e3950>
I close this ticket as I confirmed this is an intended behavior. The loads
has ignore
option that decides if using a reconstructed class or using the existing class in the __main__
module. The code is here.
In my sample, b=B()
is a class in __main__
, but l=[B()]
is a type in builtins
. For b1
and b2
, newly reconstructed classes were discarded and replaced with the existing __main__.B
. l1
and l2
didn't change the class for their elements, so the elements use the newly reconstructed classes which have different values for the class attribute a
.