[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