python – 如果pickle模块,__reduce__函数如何正常工作?

我不明白__reduce__函数如何在
Python中的pickle模块中完全有效.

假设我有以下课程:

class Foo(object):
  def __init__(self, file_name = 'file.txt'):
    self.file_name = file_name
    self.f = open(self.file_name, 'w')

它不能被腌制,因为pickle模块不知道如何编码文件句柄:

foo = Foo()
print(pickle.dumps(foo))

输出:

TypeError: can't pickle file objects

但是,如果我添加__reduce__函数,它会成功编码:

import pickle

class Foo(object):
  def __init__(self, file_name = 'file.txt'):
    self.file_name = file_name
    self.f = open(self.file_name, 'w')

  def __reduce__(self):
    return (self.__class__, (self.file_name, ))

foo = Foo()
print(pickle.dumps(foo))

输出:

c__main__
Foo
p0
(S'file.txt'
p1
tp2
Rp3
.

我是对的,如果pickle.dumps调用失败,__ reduce__函数只是为解构器返回“指令”重新创建原始对象?

从文档中我不清楚.

最佳答案 你是对的. __reduce__方法应该返回提示如何重建(unpickle)对象,以防它无法自动腌制.它可能包含一个对象引用和参数,通过它可以调用它来创建对象的初始版本,对象的状态等.

documentation

If a string is returned, the string should be interpreted as the name of a global variable. It should be the object’s local name relative to its module; the pickle module searches the module namespace to determine the object’s module. This behaviour is typically useful for singletons.

When a tuple is returned, it must be between two and five items long. Optional items can either be omitted, or None can be provided as their value. The semantics of each item are in order:

  • A callable object that will be called to create the initial version of the object.
  • A tuple of arguments for the callable object. An empty tuple must be given if the callable does not accept any argument.
  • Optionally, the object’s state, which will be passed to the object’s __setstate__() method as previously described. If the object has no such method then, the value must be a dictionary and it will be added to the object’s __dict__ attribute.
  • Optionally, an iterator (and not a sequence) yielding successive items. These items will be appended to the object either using obj.append(item) or, in batch, using obj.extend(list_of_items). This is primarily used for list subclasses, but may be used by other classes as long as they have append() and extend() methods with the appropriate signature. (Whether append() or extend() is used depends on which pickle protocol version is used as well as the number of items to append, so both must be supported.)
  • Optionally, an iterator (not a sequence) yielding successive key-value pairs. These items will be stored to the object using obj[key] = value. This is primarily used for dictionary subclasses, but may be used by other classes as long as they implement __setitem__().
点赞