Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
is 'self' optional ?
#2
Quote:
   def open_branch(self):
self identifies this as an instance method, whereas without it would be a class method. 

Quote:Code still works with self removed.
you never actually called the open_branch method if you did via the isntance it would give you the error
Error:
Traceback (most recent call last):   File "test1.py", line 9, in <module>     x.open_branch() TypeError: open_branch() takes no arguments (1 given)
same with the withdra method, if you removed self, you would get 
Error:
Traceback (most recent call last):   File "test1.py", line 12, in <module>     my_account.withdraw(5) TypeError: withdraw() takes exactly 1 argument (2 given)
my_account instance is calling a method it expects to take the first parameter as itself

http://neopythonic.blogspot.com/2008/10/...-stay.html
Guido van Rossum Wrote:Bruce Eckel has blogged about a proposal to remove 'self' from the formal parameter list of methods. I'm going to explain why this proposal can't fly.

Bruce's Proposal

Bruce understands that we still need a way to distinguish references to instance variables from references to other variables, so he proposes to make 'self' a keyword instead. Consider a typical class with one method, for example:

class C:
  def meth(self, arg):
     self.val = arg
     return self.val
Under Bruce's proposal this would become:

class C:
  def meth(arg):  # Look ma, no self!
     self.val = arg
     return self.val
That's a saving of 6 characters per method. However, I don't believe Bruce proposes this so that he has to type less. I think he's more concerned about the time wasted by programmers (presumably coming from other languages) where the 'self' parameter doesn't need to be specified, and who occasionally forget it (even though they know better -- habit is a powerful force). It's true that omitting 'self' from the parameter list tends to lead to more obscure error messages than forgetting to type 'self.' in front of an instance variable or method reference. Perhaps even worse (as Bruce mentions) is the error message you get when the method is declared correctly but the call has the wrong number of arguments, like in this example given by Bruce:

Error:
Traceback (most recent call last): File "classes.py", line 9, in   obj.m2(1) TypeError: m2() takes exactly 3 arguments (2 given)
I agree that this is confusing, but I would rather fix this error message without changing the language.

Why Bruce's Proposal Can't Work

Let me first bring up a few typical arguments that are brought in against Bruce's proposal.

There's a pretty good argument to make that requiring explicit 'self' in the parameter list reinforces the theoretical equivalency between these two ways of calling a method, given that 'foo' is an instance of 'C':
foo.meth(arg) == C.meth(foo, arg)
Another argument for keeping explicit 'self' in the parameter list is the ability to dynamically modify a class by poking a function into it, which creates a corresponding method. For example, we could create a class that is completely equivalent to 'C' above as follows:
# Define an empty class:

class C:
  pass
# Define a global function:

def meth(myself, arg):
  myself.val = arg
  return myself.val
# Poke the method into the class:
C.meth = meth
Note that I renamed the 'self' parameter to 'myself' to emphasize that (syntactically) we're not defining a method here. Now instances of C have a method with one argument named 'meth' that works exactly as before. It even works for instances of C that were created before the method was poked into the class.

I suppose that Bruce doesn't particularly care about the former equivalency. I agree that it's more of theoretical importance. The only exception I can think of is the old idiom for calling a super method. However, this idiom is pretty error-prone (exactly due to the requirement to explicitly pass 'self'), and that's why in Python 3000 I'm recommending the use of 'super()' in all cases.

Bruce can probably think of a way to make the second equivalency work -- there are some use cases where this is really important. I don't know how much time Bruce spent thinking about how to implement his proposal, but I suppose he is thinking along the lines of automatically adding an extra formal parameter named 'self' to all methods defined directly inside a class (I have to add 'directly' so that functions nested inside methods are exempted from this automatism). This way the first equivalency can be made to hold still.

However, there's one situation that I don't think Bruce can fix without adding some kind of ESP to the compiler: decorators. This I believe is the ultimate downfall of Bruce's proposal.

When a method definition is decorated, we don't know whether to automatically give it a 'self' parameter or not: the decorator could turn the function into a static method (which has no 'self'), or a class method (which has a funny kind of self that refers to a class instead of an instance), or it could do something completely different (it's trivial to write a decorator that implements '@classmethod' or '@staticmethod' in pure Python). There's no way without knowing what the decorator does whether to endow the method being defined with an implicit 'self' argument or not.

I reject hacks like special-casing '@classmethod' and '@staticmethod'. I also don't think it would be a good idea to automagically decide whether something is supposed to be a class method, instance method, or static method from inspection of the body alone (as someone proposed in the comments on Bruce's proposal): this makes it harder to tell how it should be called from the 'def' heading alone.

In the comments I saw some pretty extreme proposals to save Bruce's proposal, but generally at the cost of making the rules harder to follow, or requiring deeper changes elsewhere to the language -- making it infinitely harder to accept the proposal as something we could do in Python 3.1. For 3.1, by the way, the rule will be once again that new features are only acceptable if they remain backwards compatible.

The one proposal that has something going for it (and which can trivially be made backwards compatible) is to simply accept
def self.foo(arg): ...
inside a class as syntactic sugar for
def foo(self, arg): ...
I see no reason with this proposal to make 'self' a reserved word or to require that the prefix name be exactly 'self'. It would be easy enough to allow this for class methods as well:

@classmethod

def cls.foo(arg): ...
Now, I'm not saying that I like this better than the status quo. But I like it a lot better than Bruce's proposal or the more extreme proposals brought up in the comments to his blog, and it has the great advantage that it is backward compatible, and can be evolved into a PEP with a reference implementation without too much effort. (I think Bruce would have found out the flaws in his own proposal if he had actually gone through the effort of writing a solid PEP for it or trying to implement it.)

I could go on more, but it's a nice sunny Sunday morning, and I have other plans... :-)

Posted by Guido van Rossum
Recommended Tutorials:
Reply


Messages In This Thread
is 'self' optional ? - by meems - Nov-25-2016, 08:33 PM
RE: is 'self' optional ? - by metulburr - Nov-25-2016, 09:36 PM
RE: is 'self' optional ? - by Ofnuts - Nov-25-2016, 09:39 PM
RE: is 'self' optional ? - by meems - Nov-26-2016, 12:45 AM
RE: is 'self' optional ? - by metulburr - Nov-26-2016, 02:13 AM
RE: is 'self' optional ? - by nilamo - Dec-06-2016, 08:11 PM
RE: is 'self' optional ? - by metulburr - Dec-06-2016, 08:53 PM
RE: is 'self' optional ? - by nilamo - Dec-06-2016, 10:26 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  using mutable in function defintion as optional paramter akbarza 8 497 Apr-27-2024, 09:59 PM
Last Post: snippsat
  Trouble making an argument optional linuxnoob 2 2,945 Aug-31-2018, 01:52 AM
Last Post: linuxnoob

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020