[Python-Dev] instancemethod_getattro seems to be partially wrong

Guido van Rossum guido at python.org
Wed Nov 19 00:07:05 EST 2003

> Hi Guido,
> ...
> > Um, my brain just did a double-take.  Standard Python doesn't let you
> > do that, so you must be changing some internals.  Which parts of
> > Python are you trying to change and which parts are you trying to keep
> > unchanged?  If you were using a different metaclass you could just
> > create a different implementation of instancemethod that does what you
> > want, so apparently you're not going that route.  (With new-style
> > classes, instancemethod isn't that special any more -- it's just a
> > currying construct with some extra baggage.)
> No no no, I'm not fiddling around with any internals, here.
> I just want to use the machinary as it is, and to be able to
> pickle almost everything.
> So, if somebody did a v=C().x, I have that variable around.
> In order to pickle it, I ask for its __reduce__, or in other
> words, I don't ask for it, I try to supply it, so the pickling
> engine can find it.

But how, I wonder, are you providing it?  You can't subclass
instancemethod -- how do you manage to add a __reduce__ method to it
without fiddling with any internals?

> My expectation is that C().x.__reduce__ gives me the bound
> __reduce__ method of the bound x method of a C instance.

Yes, unfortunately you get the __reduce__ method of the unbound
function instead.

I think Martin is right: copy_reg may be your last hope.  (Or
subclassing pickle to special-case instancemethod.)

The pickling machinery wasn't intended to pickle bound methods or
functions etc., and doesn't particularly go out of its way to allow
you to add that functionality.

> ...
> > Try again.  I don't think that C().f.__reduce__ should be a method of
> > an instance of C.  You want it to be a method of a bound method
> > object, right?
> No, __reduce__ is a method of f, which is bound to an instance
> of C. Calling it will give me what I need to pickle the bound
> f method. This is all what I want. I think this is just natural.

And it would be except for the delegation of method attributes to
function attributes.  It is a similar aliasing problem as you see when
you try to access the __getattr__ implementation for classes as
C.__getattr__ -- you get the __getattr__ for C instances instead.  So
you have to use type(C).__getattr__ instead.  That would work for
__reduce__ too I think: new.instancemethod.__reduce__(C().f).

> >>If that's not the way to do it, which is it?
> > 
> > 
> > I think what I suggested above -- forget about the existing
> > instancemethod implementation.  But I really don't understand the
> > context in which you are doing this well enough to give you advice,
> > and in any context that I understand the whole construct doesn't make
> > sense. :-(
> Once again.
> What I try to achieve is complete thread pickling.
> That means, I need to supply pickling methods to
> all objects which don't have builtin support in
> cPickle or which don't provide __reduce__ already.
> I have done this for some 10 or more types, successfully.
> Bound PyCFunction objects are nice and don't give me a problem.
> Bound PyFunction objects do give me a problem, since they
> don't want to give me what they are bound to.

OK, so you *are* messing with internals after all (== changing C
code), right?  Or else how do you accomplish this?

> My options are:
> - Do an ugly patch that special cases for __reduce__, which I did
>    just now, in order to seet hings working.
> - get the master's voice about how to do this generally right,
>    and do it generally right.
> I would of course prefer the latter, but I also try to save
> as much time as I can while supporting my clients, since
> Stackless is almost no longer sponsored, and I have money problems.

I have a real job too, that's why I have little time to help you. :-(

--Guido van Rossum (home page: http://www.python.org/~guido/)

More information about the Python-Dev mailing list