Skip to content

Instantly share code, notes, and snippets.

@tef
Last active August 29, 2015 14:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tef/5ca02a57edbc1a498ea0 to your computer and use it in GitHub Desktop.
Save tef/5ca02a57edbc1a498ea0 to your computer and use it in GitHub Desktop.

When I was a younger, petulant mess of a programmer, I too waltzed into python and the explicit self. I'd done Java, JavaScript, and a handful of terrible languages not even worth mentioning. I didn't like it much, but I'd often used /this.foo/ instead of /foo/ in Java. I liked to be able to see what I was doing. I wasn't so keen on what seemed to be self sneaking into my method arguments. Now I've been using python for a bit, it's probably the best feature of python.

Let's take a step back and look why it's there and what it does for us: Python doesn't have methods: It has functions in classes. This means you can call a method explicitly on an object, ClassName.method(object, args). This also means you can pull the function out and assign it to other classes, ClassOne.foo = ClassTwo.foo. It also means that obj.foo() is actually two operations, method = obj.foo; method(). The choice of making methods out functions gives us unique ways to build classes, and also lets us take a method and pass it around as a function.

This is incredibly useful, and it's obvious to see why when we compare it to other languages with objects.

In Ruby, you don't even have functions, there isn't really a notion of them. A top level def foo ... end is actually defining a private method on Object. I'll let that sink in: there are no functions in ruby. defining a top level method is monkey patching object. You also have to clumsily call method = object.method(:name_of_method), method.call(), to get the same results. Ruby ends up with a plethora of things that look like functions but all behave differently. Lambdas, Blocks, Procs, Methods.

[The absolute broken nature of ruby's ersatz functions is that adding methods to Object is considered routine, and returning a class from inside a method, which captures method arguments is considered wtf. They are living in a world where mashing everything into one namespace makes sense and Foo = namedtuple('Foo', 'x y') is crazy talk.]

In javascript, when do obj.foo(), and you do method = obj.foo; method() they do two entirely different things. JavaScript programmers must manually bind methods to objects if they want to capture them to pass around. Let us not forget var that = this — this isn't like a variable, nor acts like one, it doesn't obey the scoping rules that other languages have.

In python: methods are functions, and when you lookup obj.foo, it partially applies the function, setting the first argument to obj. self is just like any other argument, and can be captured inside nested function and class definitions. In many ways, it's not explicit self, but lexical self. it's just another variable, which is why you can call it anything you like. Python could chose to have both method and function types, and special self keyword, but we'd be doing this = self to lexically bind it, and also fun doing bind and unbind to play about with methods.

It gives you all of this expressive power and how do you thank it? Trying to rename it from something every python programmer calls it, and every python programmer has a habit of writing it. Why do you claim to do it? Readability? Optimization? Time saving. You have already saved yourself so much time by using lexical self that one or two keystrokes isn't going to make a project late.

Whining about lexical self and arguing to remove or shorten it for the very reasons lexical self exists. Lexical self is the best goddam thing in python, take a seat, shut the fuck up, and learn why it's there. I have no fucking patience for such foolish behaviour.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment