This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author nati
Recipients
Date 2004-11-30.01:26:36
SpamBayes Score
Marked as misclassified
Message-id
In-reply-to
Content
Logged In: YES 
user_id=63133

This infinite recursion also occurs in another place, that
got me stumped for a couple of days when old code that
worked with Python 2.2 stopped working.  If __class__ is not
fidgeted with (as in original bug report), but a descriptor
returns a custom reduce for the class, but not for its
objects, reduce enters an infinite loop on the object:

"""
class descriptor_for_reduce(object):
    def __get__(self,obj,tp=None):
        if obj is not None: return
super(ASpecialClass,obj).__reduce__
        return self.reducer
    def reducer(self,proto=None):
        return "VerySpecial"

class ASpecialClass(object):
    __reduce__ = descriptor_for_reduce()

copy.copy(ASpecialClass())
"""

ASpecialClass().__reduce__ is object.__reduce__, which is
implemented by typeobject.c:object_reduce_ex.  This function
(that doesn't know if its called as the __reduce__ or the
__reduce_ex__ method) tries to detect if the object's
__reduce__ is overridden.  It does so by checking if the
object's class's __reduce__ is overridden, and in fact it
is.  It then assumes that the object's __reduce__ is
overridden, and calls it.  But the object's __reduce__ is
the same function, causing the infinite loop.

If __reduce_ex__ is used instead of __reduce__, the problem
goes away, ASpecialClass().__reduce_ex__() return the usual
tuple, and ASpecialClass.__reduce_ex__() return
"VerySpecial".  But when __reduce__ is overridden,
ASpecialClass().__reduce__() enters an infinite loop.

I believe this is a legitimate example that should behave
just as when __reduce_ex__ is overridden.  The example
doesn't lie about __class__, and it is certainly legitimate
for define a property that behaves differently for the class
and for its objects.

Where did this come up and why would I ever care about a
class's __reduce__?  The __reduce__ attribute of a class is
never used by (the standard) pickle or copy, since
save_global() is called instead. However, I have a custom
pickler, implemented as a subclass of pickle.Pickler, which
falls back on the class's __reduce__ when save_global()
fails.  This way, I can pickle certain classes that are
created at run-time (and can be easily recreated, e.g. from
their bases and dictionaries).
History
Date User Action Args
2007-08-23 14:20:51adminlinkissue931877 messages
2007-08-23 14:20:51admincreate