Python 3如何知道如何pickle扩展类型,特别是Numpy数组?

问题描述:

numpy的阵列,作为扩展类型(使用在扩展的C API又名定义),声明Python解释的范围(外附加字段例如data属性,它是一个Buffer Structure,如在numpy的的array interface记载。
要能够将其序列化,Python 2的用惯了__reduce__函数作为pickle协议的一部分,如在doc说明,并解释herePython 3如何知道如何pickle扩展类型,特别是Numpy数组?

但是,即使__reduce__仍然存在在Python 3,Pickle protocol部(和Pickling and unpickling extension types更多)被从文档中删除,所以目前还不清楚什么是。
此外,有涉及酸洗扩展类型的附加输入:

  • copyreg,描述为Pickle interface constructor registration for extension types,但有该copyreg模块本身中没有扩展类型的提。
  • PEP 3118 -- Revising the buffer protocol它为Python 3发布了一个新的缓冲区协议。(也许自动对这个缓冲区协议进行酸洗)。
  • 新式课堂:可以假设新式课堂对酸洗过程有影响。

那么,如何将所有这些涉及到numpy的数组:

  1. 不numpy的阵列实现特殊的方法,如__reduce__通知的Python如何腌制他们(或copyreg)? Numpy对象仍然公开__reduce__方法,但可能出于兼容性原因。
  2. Numpy是否使用Pickle开箱即用的Python C-API结构(如新的buffer protocol),所以为了泡制numpy数组,不需要补充任何东西?
+3

'__reduce__'仍然存在于Python 3中。 –

+0

.. [这里是'__reduce__'在Python 3中提到的文档](https://docs.python.org/3/library/pickle。 HTML?亮点=泡菜#对象.__ reduce__)。 – Phillip

+0

关键是,即使'reduce'仍然存在,删除'reduce'文档中的扩展类型也被删除。但是,据说接受的答案(以及以下评论)指出,这仍然是正确的。 – Phylliade

Python 3 picklesupports __reduce__,它涵盖在Pickling Class Instances section下。

numpy的支持在这方面没有改变;它在阵列上实现__reduce__支持酸洗中任一的Python 2或3:

>>> import numpy 
>>> numpy.array(0).__reduce__() 
(<built-in function _reconstruct>, (<class 'numpy.ndarray'>, (0,), b'b'), (1,(), dtype('int64'), False, b'\x00\x00\x00\x00\x00\x00\x00\x00')) 

返回一个三元素的元组,由一个功能对象的重新创建的值,的参数为函数的元组,和一个状态元组通过否newinstance.__setstate__()

+0

那么在[Pickling和Unpickling扩展类型](https://docs.python.org/2.7/library/pickle.html#pickling-and-unpickling-extension-types)中说什么仍然是正确的?为什么他们将'__reduce__'文件从'扩展类型'移动到更一般的'类实例'部分? – Phylliade

+1

@Phylliade:是的,一切都是真的。该方法并不是专用于扩展类型的(并且自定义Python类和扩展类型之间的界线在很大程度上已被模糊)。 –

+1

@Phylliade:'__reduce__'是较低级的复制协议实现;如果可能的话,自定义Python类应该实现更高级别的('__getnewargs_ex__'/'__getstate__' /'__setstate__')方法),然后使用默认的__reduce__实现。 –