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:
Guido van Rossum 2003-02-03 20:22:23 +00:00
parent 2c9210a9b5
commit 90133d7f6a
1 changed files with 156 additions and 0 deletions

View File

@ -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!