Python 不能泡菜 getset_descriptor

Python cant pickle getset_descriptor

我正在尝试 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

我知道复制模块正在尝试使用 pickle 模块用于复制的函数。 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.

问题是,d 的类型是 dict。我们可以深度复制字典:

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

所以如果 d 的类型是 dict,为什么我不能深度复制它?或者 d 的类型不是真正的字典,它只是 Python 中的 hack 吗?

d 确实是一本字典。您 运行 遇到的问题是 pickle 无法独立于 class 序列化 classes 的方法和属性。当您查看 d 的内容时,您会看到:

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

__dict____weakref__ 的值是 MyClass 对象的属性。如果不 also 序列化 MyClass,则无法序列化它们。

此外,如果您检查其中每一个的类型,您会发现这是您所看到的错误的来源:

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