Python не могу засолить getset_descriptor - PullRequest
0 голосов
/ 05 февраля 2020

Я пытался что-то с types.MappingProxyType:

class MyClass:
    l = [1, 2]

proxy = MyClass.__dict__

Затем я хотел извлечь словарь из этого прокси:

d = proxy.copy()

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

Затем я хотел добавить что-то к значению списка d:

d["l"].append(3)

Но это также влияет на proxy (точно):

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

Я хотел не влиять на наш proxy, поэтому я попытался использовать copy.deepcopy:

import copy

dict_2 = copy.deepcopy(d)

И это выдало ошибку:

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

Я знаю, что модуль копирования пытается использовать функции, которые используются модулем консервирования для копирования. https://docs.python.org/3/library/copy.html#copy .deepcopy

Классы могут использовать те же интерфейсы для управления копированием, которые они используют для управления протравливанием. См. Описание модуля pickle для получения информации об этих методах. Фактически, модуль копирования использует зарегистрированные функции выбора из модуля copyreg.

Проблема в том, что тип d равен dict. И мы можем сделать глубокой копии:

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

Итак, если тип d равен dict, почему я не могу сделать глубокую копию? Или тип d на самом деле не диктат и это всего лишь взлом в Python?

1 Ответ

1 голос
/ 05 февраля 2020

d действительно словарь. Проблема, с которой вы сталкиваетесь, заключается в том, что pickle не может сериализовать методы и атрибуты классов независимо от класса. Когда вы смотрите на содержимое d, вы видите:

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

Значения __dict__ и __weakref__ являются атрибутами объекта MyClass. Вы не можете сериализовать их без и сериализации MyClass.

Кроме того, если вы проверите тип каждого из них, вы увидите, что именно здесь возникает ошибка:

type(d['__dict__']), type(d['__weakref__'])
# returns:
(getset_descriptor, getset_descriptor)
...