Why do class methods always need 'self' as the first parameter?

John Roth johnroth1 at gmail.com
Fri Sep 2 18:30:35 EDT 2011


On Sep 2, 2:30 pm, Ian Kelly <ian.g.ke... at gmail.com> wrote:
> On Fri, Sep 2, 2011 at 11:51 AM, John Roth <johnro... at gmail.com> wrote:
> >> I don't see how you could get rid of the wrappers.  Methods would
> >> still need to be bound, somehow, so that code like this will work:
>
> >> methods = {}
> >> for obj in objs:
> >>     if obj.is_flagged:
> >>         methods[obj.user_id] = obj.do_work
> >>     else:
> >>         methods[obj.user_id] = obj.do_other_work
> >> # ...
> >> methods[some_user_id]()
>
> >> Without method wrappers, how does the interpreter figure out which
> >> instance is bound to the method being called?
>
> >> Cheers,
> >> Ian
>
> > Good question.
>
> > Currently the instance wrapper is created during method instantiation,
> > so the instance is obviously available at that point. There are two
> > rather obvious ways of remembering it. One is to use the invocation
> > stack, which has the instance. Another would be for the compiler to
> > create a local variable for the instance and possibly the class and
> > fill them in at instantiation time. Both of these require fixing the
> > names "self" and "cls" so the compiler knows what to do with them. The
> > first would require giving these two names their own bytecodes, the
> > second makes them simple local variables the same as the ones in the
> > method headers. The latter also allows them to be changed by the
> > method, which is probably not the world's best programming practice
> > although it's possible now.
>
> That's not what I asked.  Both of those options are storing the
> instance within a stack frame, once it's been called.  I'm asking how
> you would remember the instance during the interval from the time when
> the method
> is accessed until when it has been called.
>
> In the code above, the method is accessed just before it is stored in
> the dictionary.  That is when the method wrapper is currently created,
> and the instance is available.  It is not called until much later,
> possibly not even within the same function.  How would you remember
> the instance over that period without wrapping the function?
>
> Cheers,
> Ian

I see what you're saying now - I didn't get your example the first
time. So the optimization of eliminating the instance wrapper is only
possible if it's retrieved via the instance and then called
immediately. That would seem to be a useful optimization if it was
possible - I wonder if PyPy is doing it since they've got that fancy
JIT, and it would seem that an immediate call after retrieving the
method is overwhelmingly more frequent than saving it for later.

I think it's still true that calling the underlying function object
through the instance wrapper requires remaking the parameter list,
which seems to be another piece of unnecessary overhead, unless
there's a fast path through the call machinery that treats the
instance specially.

It does, however, decouple the two issues so I can't claim the
optimization as a benefit. Drat.

John Roth



More information about the Python-list mailing list