I prefer version 3 by far. Unfortunately, Javascript decided to take the same path with ES6 classes which forces you to use this in the body. Fortunately, it does not force you to use this in the argument list.
I think that goes against the python dogma of "Explicit is better than implicit." In #1 and #2 there is no question about where 'x' comes from, while in #3 it could be a class variable or a global variable or from just about anywhere.
The beauty with self in Python is that self is not at all magic : it merely indicates that the object instance you're using will be passed as first argument of the class method.
Also you can get a custom font with typographic ligatures (e.g. for self, lambda, and so on) in order to make it more visually appealing. For instance (self > 圖) :
You can get the "Python dogma" with `import this`. "Explicit is better than implicit" is part of it, but so is "practicality beats purity" (and "There should be one-- and preferably only one --obvious way to do it, although that way may not be obvious at first unless you're Dutch").
...Doesn't work with `self` because that would be implicit again, though.
Anyway, I think that it is a minor inconvenience that isn't important for oneliners and extremely helpful when reading larger functions.
It actually uses less characters, since you've eliminated all the repeated uses of 'this.'. As a general rule I'm in favor of a turning a one liner into a two liner if it improves readability, especially when it reduces actual typing.
Python's self in the arglist is a C struct pointer sneaking in from the 80's, which is the time when Python has been designed. It could be excused but there should be a deprecation PEP by now. Make it a keyword and let us type it only when we need it.
That might seem nice for your limited example, but it breaks down when you realize that in example #3 there would be no easy way to differentiate between scopes.
y = 100
x = 15
class MyClass(object):
x = 50
def __init__(self, x):
self.x = x
def length():
return x * y
What does that mean? Does MyClass(10).length() raise an AttributeError because MyClass doesn't have an attribute named y? Does it automatically recognize there's a y in the outer scope and use that, or does it call __getattr__ first (i.e. method that gets called when a missing attribute is accessed)? Furthermore, how do I specify that I want to access the class attribute x, or that I want to access the nonlocal x?
In my opinion, there are far bigger problems with pythons scoping. Why is for/if/etc not it's own scope? You can define a temporary variable in there and mistakenly use it somewhere down the line. In a "for i in ..", the i should be cleared after the loop but it isn't. Why can't you create a new scope within a function? This allows you to bundle related stuff together and be sure the scope is cleared afterwards, so as to not mistakenly reuse variables. The thing that you're promoting as an advantage of explicit self is already broken by having a single scope for the whole function.
Blocks like this are an imensely useful way to keep scopes clean:
int someMethod(){
...
{ // some small stuff that doesn't warrant a new method but you don't want it to bleed into the remaining part of the function, e.g.:
float x = readNextFloat();
float y = readNextFloat();
float z = readNextFloat();
float length = sqrt(x*x + y*y + z*z);
cout << length;
}
// do some other things without worrying about potentially initialized variables
...
}
Don't call it "s", because then you break consistency basically with the whole Python ecosystem. That's not very nice for fellow programmers who already used to read and understand "self".