# 1
def length(self):
return math.sqrt(self.x*self.x + self.y*self.y + self.z*self.z)
# 2
def length(self):
return math.sqrt(self.x**2 + self.y**2 + self.z**2)
# 3
def length():
return math.sqrt(x*x + y*y + z*z)
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. function length() {
const { x, y, z } = this
return math.sqrt(x * x + y * y + z * z)
}
I think it's pretty short, readable and explicit.EDIT: formatting
struct Foo { x: f64, y: f64, z: f64 }
fn length(Foo {x, y, z}: Foo) -> f64 {
(x*x + y*y + z*z).sqrt()
}
...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.AFAIK it doesn't work on self because the [&[mut ]]self parameter is more or less a keyword determining ownership interaction with the call subject.
The UFCS RFC would have made it sugar for `self: [&[mut ]]Self` (IIRC) but I believe that floundered.
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.
# 4
def length():
return math.sqrt(.x**2 + .y**2 + .z**2)
Ambiguity and "pseudo-keyword" are both gone![EDITED code for better readability]
def length(s):
return math.sqrt(s.x**2 + s.y**2 + s.z**2)
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 > 圖) :
def length(圖):
return math.sqrt(圖.x**2 + 圖.y**2 + 圖.z**2)- No static types
- A variable might belong to the scope of a method, object or class, depending on where it was first set and changed afterwards
- Implicit execution of code on import of a module (__init__.py, including parent packages)
- Any object is truthy or falsey, i.e. conditional statements don't require an explicit boolean
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?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
...
}That seems to be an example of not using an implicit self.
> A different name for the variable fixes it
There's nothing to fix, it works just fine.
In fact, our coding style demands that we avoid using instance variables in preference of adding `attr_accessor` to explicitly encourage the use of implicit self.