【问题标题】:Python cant pickle getset_descriptorPython 不能腌制 getset_descriptor
【发布时间】:2020-02-04 21:47:55
【问题描述】:

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

类可以使用相同的接口来控制它们使用的复制 控制酸洗。请参阅模块pickle的描述 这些方法的信息。实际上,复制模块使用 从 copyreg 模块注册泡菜函数。

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

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

如果d 的类型是dict,为什么我不能对其进行深度复制?或者d 的类型不是真正的 dict,它只是 Python 中的一个 hack?

【问题讨论】:

  • 这和标题和标签中提到的泡菜有什么关系?
  • @myke,看错误回溯
  • @myke 也请看documents:“类可以使用与控制酸洗相同的接口来控制复制。有关这些方法的信息,请参见模块pickle的描述。事实上, copy 模块使用 copyreg 模块中注册的 pickle 函数。”

标签: python dictionary pickle deep-copy


【解决方案1】:

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)

【讨论】:

    猜你喜欢
    • 2021-11-01
    • 2017-02-22
    • 2021-02-02
    • 1970-01-01
    • 1970-01-01
    • 2018-04-22
    • 1970-01-01
    • 2014-10-27
    • 2016-03-27
    相关资源
    最近更新 更多