[Python-3000] Removing 'self' from method definitions

Ian Bicking ianb at colorstudy.com
Thu Apr 13 18:41:43 CEST 2006


OK, so first Guido says he wants people to speculate less, then he says 
he wants them to speculate more.  Who knows.  So, now I speculate more.

I propose that the self argument be removed from method definitions.  It 
would not be removed from other places, e.g., you'd still use 
"self.foo()", but the definition for that method would be "def foo():".

One data point: after years of doing this, I still make this mistake 
nearly every day:

   def doit(self):
       blah blah
       x = result of blah blah
       more stuff

Then refactor to:

   def doit(self):
       x = self.get_x(self)
       more stuff

   def get_x(self):
       return blah blah

Why do I keep doing this?  I don't know, mabye it's because I usually 
copy the "blah blah" to a new function definition, write the signature 
there, then mentally copy that signature back into the original 
function.  I'm not the only one; this is one of the most common 
criticisms of Python, probably on par with significant whitespace. 
People might be wrong on whitespace, but not on this.

What are the advantages of the current behavior?

* You can name the first argument whatever you want.  I could say 
something snarky about this, but that's probably not necessary.

* Functions are functions wherever you define them; only access 
determines if a function is a "method".

* Scoping is explicit.  It becomes hard to determine where "self" is 
defined if any function could be invoked as a method.

* Decorator wrappers work more easily on both functions and methods when 
the wrapping is just passing through its arguments.  If the decorator 
has to understand the arguments in any then it becomes more difficult.

I propose: 'self' and 'cls' implicit arguments.  Their presence as the 
first argument to a function or method will be ignored, for backward 
compatibility.

Problems:

This wouldn't work:

     def get_writer(self):
         def write(item):
             self.write_item(item)
         return write

Right now you can tell that 'self' comes from the enclosing function; if 
self is an implicit argument, then this won't work anymore.  In 
Javascript they solve this same issue with the pattern:

     def get_writer():
         this = self
         def write(item):
             this.write_item(item)
         return write

This is admittedly lame, but I can't think of any resolution.

I think this should still work fine:

     def some_method():
         return self.foo()+1
     SomeClass.some_method = some_method

However, some_method() could not be called outside of a method-like 
context (if it was you'd get a NameError or subclass thereof).  At the 
least you could still do some_method.__get__(self_like_object)(); maybe 
a nicer method could be provided as well.

The traditional way of calling superclass methods and getting an unbound 
method should still work.  It just won't be symmetric with the way the 
functions are defined.  Since this is not the typical way methods are 
called, it seems reasonable.

-- 
Ian Bicking  /  ianb at colorstudy.com  /  http://blog.ianbicking.org


More information about the Python-3000 mailing list