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,
|
functions). The return values are interpreted exactly the same,
|
||||||
though, and we'll refer to these collectively as __reduce__.
|
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
|
__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
|
a string, this is an object whose state is not to be pickled, but
|
||||||
instead a reference to an equivalent object referenced by name.
|
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).
|
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
|
The __newobj__ unpickling function
|
||||||
|
|
||||||
When the unpickling function returned by __reduce__ (the first
|
When the unpickling function returned by __reduce__ (the first
|
||||||
|
@ -237,6 +253,146 @@ The __newobj__ unpickling function
|
||||||
Python 2.3.
|
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
|
TBD
|
||||||
|
|
||||||
The rest of this PEP is still under construction!
|
The rest of this PEP is still under construction!
|
||||||
|
|
Loading…
Reference in New Issue