-1

I was trying something with types.MappingProxyType:

class MyClass:
    l = [1, 2]

proxy = MyClass.__dict__

Then I wanted to extract dictionary from this Proxy:

d = proxy.copy()

print(type(d))
#<class 'dict'>

Then I wanted to append something to list value of d:

d["l"].append(3)

But this also affects proxy (for sure):

>>> print(proxy["l"])
[1, 2, 3]

I wanted to not affect our proxy, so I tried using copy.deepcopy:

import copy

dict_2 = copy.deepcopy(d)

And it gived an error:

Traceback (most recent call last):
  File "C:\Users\Dinçel\AppData\Local\Programs\Python\Python37\istihza.py", line 18, in <module>
    dict_2 = copy.deepcopy(d)
  File "C:\Users\Dinçel\AppData\Local\Programs\Python\Python37\lib\copy.py", line 150, in deepcopy
    y = copier(x, memo)
  File "C:\Users\Dinçel\AppData\Local\Programs\Python\Python37\lib\copy.py", line 240, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
  File "C:\Users\Dinçel\AppData\Local\Programs\Python\Python37\lib\copy.py", line 169, in deepcopy
    rv = reductor(4)
TypeError: can't pickle getset_descriptor objects

I know that the copy module is trying to use functions which are used by pickle module for copying. https://docs.python.org/3/library/copy.html#copy.deepcopy

Classes can use the same interfaces to control copying that they use to control pickling. See the description of module pickle for information on these methods. In fact, the copy module uses the registered pickle functions from the copyreg module.

The problem is that, type of d is dict. And we can deepcopy dicts:

copy.deepcopy({"this":["is", "a", "dict"]})

So if type of d is dict, why I cant deepcopy it? Or is the type of d is not really dict and is it only a hack in the Python?

Ekrem Dinçel
  • 1,053
  • 6
  • 17
  • 1
    What does this have to do with pickle, which is mentioned in the title and as a tag? – myke Feb 04 '20 at 21:54
  • 1
    @myke, look at the error traceback – James Feb 04 '20 at 21:54
  • @myke Also look at the [documents](https://docs.python.org/3/library/copy.html#copy.deepcopy) please : "Classes can use the same interfaces to control copying that they use to control pickling. See the description of module pickle for information on these methods. In fact, the copy module uses the registered pickle functions from the copyreg module." – Ekrem Dinçel Feb 04 '20 at 21:56
  • Does this help? [Program to work out an age gives error about a getset_descriptor?](https://stackoverflow.com/questions/41409301/program-to-work-out-an-age-gives-error-about-a-getset-descriptor) – myke Feb 04 '20 at 22:03

1 Answers1

2

d is indeed a dictionary. The issue you are running into is that pickle cannot serialize methods and attributes of classes independent of the class. When you look at the contents of d you see:

{'__module__': '__main__',
 'l': [1, 2, 3],
 '__dict__': <attribute '__dict__' of 'MyClass' objects>,
 '__weakref__': <attribute '__weakref__' of 'MyClass' objects>,
 '__doc__': None}

The values for __dict__ and __weakref__ are attributes of the MyClass object. You cannot serialize these without also serializing MyClass.

Furthermore, if you check the type of each of these, you can see this is where the error you are seeing arises from:

type(d['__dict__']), type(d['__weakref__'])
# returns:
(getset_descriptor, getset_descriptor)
James
  • 32,991
  • 4
  • 47
  • 70