[Edu-sig] Ditch "self"?

Paul D. Fernhout pdfernhout at kurtz-fernhout.com
Wed Oct 24 19:57:25 CEST 2007


Ivan-

Thanks for the link; that's a very interesting essay. There's a lot in there
to wrap my mind around; I'll need to think about more.

>From a first reading, perhaps I could sometimes think of methods defined in
the normal indentation style within a class like a functional-programming
partial "currying" (binding some arguments in with a function call to return
a new function) when they are being built and assigned? That helps me make
more sense of the Python design approach. The approach Dethe outlined
invoking code from the "new" module:
  "a.foobar = new.instancemethod(foobar, a, a.__class__)"
seems to me to be a form of currying (although not exactly, since the class
gets involved). By the way, see for example how to generalize currying in
Python:
  http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52549
or for Python 2.5:
  http://docs.python.org/whatsnew/pep-309.html
Support is there to do currying (directly in Python2.5 or via kludges in
earlier versions), but it still kind of an add-on to Python is feels to me.

This still leaves me wondering about the issue what happens when an instance
gets the method definition from a class? That's not quite curried in a
sense, since the method is stored in the class, not the instance, and is
specialized on the fly for use with the instance. It seems inconsistent to
me, even though it works in practice. :-) And it seems one reason why having
"self" in a method definition like it was a regular argument is somewhat
misleading, since it seems to me that this first argument is being treated
specially, perhaps being sort-of-curried if the method is stored directly in
the instance, but being dynamically set if the method is stored in the class
or a superclass.

Also, in the prototype case,(which is admittedly out of the normal Python
real right now), assuming prototypes lookup functions in parents if they do
not implement them themselves, an instance/prototype probably wants a
function it inherits from a parent to run as if "self" was the instance it
was evoked on ("foo" in foo.bar()) as opposed to "self" still being the
parent, as in "foo.parent.bar()". This is similar but not identical to how
normal Python lookup which I refer to above where "self" is not bound to the
class for typical instance methods, but instead is bound to the particular
instance the method is called with. It seems to me that because Python does
not generally handle the previous issue raised in what I might feel is an
elegant enough and consistent way (not that I am completely sure what that
would look like :-), that implementing a prototype based system on top of
Python requires more implementation hoops to jump through and related
performance hits and cryptic error messages than it might otherwise. If, for
example, "self" was truly a namespace aspect and not in the function
definition, then it could just be looked up at run time when the function
was called or be filled into the current context on the stack; on the other
hand, if it was a curried parameter, then presumably there would be some
other means of supporting looking up methods and specifically binding
variables with certain names or in certain positions at function invocation
(or other times) which prototypes could take advantage of efficiently.

So, I feel both of these issues show a weakness in Python's conceptual model
for consistent attribute lookup related to method functions. Not that Python
does not work in practice, as it certainly does (sometimes you can either
get it working or get it right, as in "worse is better" :-). It's amazing
that prototypes work at all (like I tried with PataPata), and a real tribute
to Python's flexibility. It is just that this sort of inconsistency (as I
see it, clearly others don't agree) leads to difficulties learning and
generalizing this sort of knowledge. Python seems (historically) to treat
instance methods as curried sometimes (the direct invocation), but embedded
within a namespace in others (when found in a class). So when I think about
the value of "self" in a function definition, I lean more towards the
Smalltalk-side of it being implicitly defined and so see it as superfluous
within the definition of a function (but not the body, where I like it as
being explicit), but I can see how other people might lean towards the Lisp
or functional side where "self" is like a curried argument and so should be
explicitly defined. Python has some roots in both areas. Still, Python is
not Smalltalk, Lisp, or Haskell/OCaml, so it has its own philosophy, and own
strengths and weaknesses because of it. What it does clearly works within
certain bounds, and works well in practice for writing many interesting and
useful applications.

This is all a little abstract and I'm likely mixing Smalltalk and Pythonic
names for various things, so thanks to anybody who was willing to wade
through this comment this far. :-) I still may not fully understand
something about the Python model, so I'll need to continue to think about it
based on the feedback from you and Dethe. Thanks again for the links.

--Paul Fernhout

Ivan Krstić wrote:
> On Oct 24, 2007, at 2:57 PM, Paul D. Fernhout wrote:
>> Thanks; that was very helpful in improving my understanding of Python in
>> practice.
> 
> And for understanding the relevant theory, take a look at:
>     <http://users.rcn.com/python/download/Descriptor.htm>


More information about the Edu-sig mailing list