Added docs for __getstate__ and __setstate__, __getinitargs__ and
__getnewargs__. Unfortunately these need to be refactored again according to a different organizing principle. ;-(
This commit is contained in:
parent
2c9210a9b5
commit
90133d7f6a
156
pep-0307.txt
156
pep-0307.txt
|
@ -137,6 +137,10 @@ Extended __reduce__ API
|
|||
functions). The return values are interpreted exactly the same,
|
||||
though, and we'll refer to these collectively as __reduce__.
|
||||
|
||||
IMPORTANT: a classic class cannot provide __reduce__
|
||||
functionality. It must use __getinitargs__ and/or __gestate__ to
|
||||
customize pickling. These are described below.
|
||||
|
||||
__reduce__ must return either a string or a tuple. If it returns
|
||||
a string, this is an object whose state is not to be pickled, but
|
||||
instead a reference to an equivalent object referenced by name.
|
||||
|
@ -212,6 +216,18 @@ Extended __reduce__ API
|
|||
state (how this is done is up to the application).
|
||||
|
||||
|
||||
XXX Refactoring needed
|
||||
|
||||
The following sections should really be reorganized according to
|
||||
the following cases:
|
||||
|
||||
1. classic classes, all protocols
|
||||
|
||||
2. new-style classes, protocols 0 and 1
|
||||
|
||||
3. new-style classes, protocol 2
|
||||
|
||||
|
||||
The __newobj__ unpickling function
|
||||
|
||||
When the unpickling function returned by __reduce__ (the first
|
||||
|
@ -237,6 +253,146 @@ The __newobj__ unpickling function
|
|||
Python 2.3.
|
||||
|
||||
|
||||
The __getstate__ and __setstate__ methods
|
||||
|
||||
When there is no __reduce__ for an object, the primary ways to
|
||||
customize pickling is by specifying __getstate__ and/or
|
||||
__setstate__ methods. These are supported for classic classes as
|
||||
well as for new-style classes for which no __reduce__ exists.
|
||||
|
||||
When __reduce__ exists, __getstate__ is not called (unless your
|
||||
__reduce__ implementation calls it), but __getstate__ will be
|
||||
called with the third item from the tuple returned by __reduce__,
|
||||
if not None.
|
||||
|
||||
There's a subtle difference between classic and new-style classes
|
||||
here: if a classic class's __getstate__ returns None,
|
||||
self.__setstate__(None) will be called as part of unpickling. But
|
||||
if a new-style class's __getstate__ returns None, its __setstate__
|
||||
won't be called at all as part of unpickling.
|
||||
|
||||
The __getstate__ method is supposed to return a picklable version
|
||||
of an object's state that does not reference the object itself.
|
||||
If no __getstate__ method exists, a default state is assumed.
|
||||
There are several cases:
|
||||
|
||||
- For a classic class, the default state is self.__dict__.
|
||||
|
||||
- For a new-style class that has an instance __dict__ and no
|
||||
__slots__, the default state is self.__dict__.
|
||||
|
||||
- For a new-style class that has no instance __dict__ and no
|
||||
__slots__, the default __state__ is None.
|
||||
|
||||
- For a new-style class that has an instance __dict__ and
|
||||
__slots__, the default state is a tuple consisting of two
|
||||
dictionaries: the first being self.__dict__, and the second
|
||||
being a dictionary mapping slot names to slot values. Only
|
||||
slots that have a value are included in the latter.
|
||||
|
||||
- For a new-style class that has __slots__ and no instance
|
||||
__dict__, the default state is a tuple whose first item is None
|
||||
and whose second item is a dictionary mapping slot names to slot
|
||||
values described in the previous bullet.
|
||||
|
||||
The __setstate__ should take one argument; it will be called with
|
||||
the value returned by __getstate__ or with the default state
|
||||
described above if no __setstate__ method is defined.
|
||||
|
||||
If no __setstate__ method exists, a default implementation is
|
||||
provided that can handle the state returned by the default
|
||||
__getstate__.
|
||||
|
||||
It is fine if a class implements one of these but not the other,
|
||||
as long as it is compatible with the default version.
|
||||
|
||||
New-style classes that inherit a default __reduce__ implementation
|
||||
from the ultimate base class 'object'. This implementation is not
|
||||
used for protocol 2, and then last four bullets above apply. For
|
||||
protocols 0 and 1, the default implementation looks for a
|
||||
__getstate__ method, and if none exists, it uses a simpler default
|
||||
strategy:
|
||||
|
||||
- If there is an instance __dict__, the state is self.__dict__.
|
||||
|
||||
- Otherwise, the state is None (and __setstate__ will not be
|
||||
called).
|
||||
|
||||
Note that this strategy ignores slots. New-style classes that
|
||||
define slots and don't define __getstate__ in the same class that
|
||||
defines the slots automatically have a __getstate__ method added
|
||||
that raises TypeError. Protocol 2 ignores this __getstate__
|
||||
method (recognized by the specific text of the error message).
|
||||
|
||||
|
||||
The __getinitargs__ and __getnewargs__ methods
|
||||
|
||||
The __setstate__ method (or its default implementation) requires
|
||||
that a new object already exists so that its __setstate__ method
|
||||
can be called. The point is to create a new object that isn't
|
||||
fully initialized; in particular, the class's __init__ method
|
||||
should not be called if possible.
|
||||
|
||||
The way this is done differs between classic and new-style
|
||||
classes.
|
||||
|
||||
For classic classes, these are the possibilities:
|
||||
|
||||
- Normally, the following trick is used: create an instance of a
|
||||
trivial classic class (one without any methods or instance
|
||||
variables) and then use __class__ assignment to change its class
|
||||
to the desired class. This creates an instance of the desired
|
||||
class with an empty __dict__ whose __init__ has not been called.
|
||||
|
||||
- However, if the class has a method named __getinitargs__, the
|
||||
above trick is not used, and a class instance is created by
|
||||
using the tuple returned by __getinitargs__ as an argument list
|
||||
to the class constructor. This is done even if __getinitargs__
|
||||
returns an empty tuple -- a __getinitargs__ method that returns
|
||||
() is not equivalent to not having __getinitargs__ at all.
|
||||
__getinitargs__ *must* return a tuple.
|
||||
|
||||
- In restricted execution mode, the trick from the first bullet
|
||||
doesn't work; in this case, the class constructor is called with
|
||||
an empty argument list if no __getinitargs__ method exists.
|
||||
This means that in order for a classic class to be unpicklable
|
||||
in restricted mode, it must either implement __getinitargs__ or
|
||||
its constructor (i.e., its __init__ method) must be callable
|
||||
without arguments.
|
||||
|
||||
For new-style classes, these are the possibilities:
|
||||
|
||||
- When using protocol 0 or 1, a default __reduce__ implementation
|
||||
is normally inherited from the ultimate base class class
|
||||
'object'. This implementation finds the nearest base class that
|
||||
is implemented in C (either as a built-in type or as a type
|
||||
defined by an extension class). Calling this base class B and
|
||||
the class of the object to be pickled C, the new object is
|
||||
created at unpickling time using the following code:
|
||||
|
||||
obj = B.__new__(C, state)
|
||||
B.__init__(obj, state)
|
||||
|
||||
where state is a value computed at pickling time as follows:
|
||||
|
||||
state = B(obj)
|
||||
|
||||
This only works when B is not C, and only for certain classes
|
||||
B. It does work for the following built-in classes: int, long,
|
||||
float, complex, str, unicode, tuple, list, dict; and this is its
|
||||
main redeeming factor.
|
||||
|
||||
- When using protocol 2, the default __reduce__ implementation
|
||||
inherited from 'object' is ignored. Instead, a new pickling
|
||||
opcode is generated that causes a new object to be created as
|
||||
follows:
|
||||
|
||||
obj = C.__new__(C, *args)
|
||||
|
||||
where args is either the empty tuple, or the tuple returned by
|
||||
the __getnewargs__ method, if defined.
|
||||
|
||||
|
||||
TBD
|
||||
|
||||
The rest of this PEP is still under construction!
|
||||
|
|
Loading…
Reference in New Issue