[Python-checkins] python/nondist/peps pep-0307.txt,1.6,1.7
gvanrossum@users.sourceforge.net
gvanrossum@users.sourceforge.net
Mon, 03 Feb 2003 12:22:26 -0800
Update of /cvsroot/python/python/nondist/peps
In directory sc8-pr-cvs1:/tmp/cvs-serv17587
Modified Files:
pep-0307.txt
Log Message:
Added docs for __getstate__ and __setstate__, __getinitargs__ and
__getnewargs__. Unfortunately these need to be refactored again
according to a different organizing principle. ;-(
Index: pep-0307.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/peps/pep-0307.txt,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -d -r1.6 -r1.7
*** pep-0307.txt 3 Feb 2003 17:50:16 -0000 1.6
--- pep-0307.txt 3 Feb 2003 20:22:23 -0000 1.7
***************
*** 138,141 ****
--- 138,145 ----
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
***************
*** 213,216 ****
--- 217,232 ----
+ 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
***************
*** 236,239 ****
--- 252,395 ----
in the recommended implementation of __newobj__ that depends on
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.