[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
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