copy modules of the standard library make use of a class’s
__reduce__() method for customizing their pickle/copy process. They seem to have a consistent view of the first 5 elements of the returned tuple:
(func, args, state, listiter, dictiter) but the 6th element seems different. For
state_setter , a callable with signature
state_setter(obj, state)->None , but for
deepcopy with signature
deepcopy(arg: T, memo) -> T .
This seems to be unintentional, since the pickle documentation states:
As we shall see, pickle does not use directly the methods described above. In fact, these methods are part of the copy protocol which implements the
__reduce__()special method. The copy protocol provides a unified interface for retrieving the data necessary for pickling and copying objects. 4
It seems like in order to make a class definition for
__reduce__() returning all 6 elements, then the
__reduce__() would have to do something very awkward like examining its call stack in order to determine if it is being called in pickle or copy context in order to return an appropriate callable? (Naively providing the same callable in both contexts would cause errors for one or the other).
Is the situation that the 6th element is unsafe to return for a class that supports both pickle and copy (in which case the documentation of pickle and copy should be updated with this caveat) or is there some way to fix the APIs eg maybe providing an
in_pickle_context_q() helper to package up the fragile stack inspection?