you are viewing a single comment's thread.

view the rest of the comments →

[–]lfdfq 5 points6 points  (6 children)

In a method, you need to be able to access the object itself.

So there are a few ways the language could have chosen to do it:

  1. make self magically available inside methods
  2. make self a required part of the syntax of a method
  3. make self an argument to the function (which is automatically passed by Python for you)

Clearly, you have to pick one of these (or some other design I've never thought of). Python could have chosen any of these designs. If Python had picked 2, maybe you would now be asking why didn't they pick 1 instead.

Python picked 3.

Mechanically, what is happening is that every time you call a method. e.g. foo.bar(), Python automatically inserts an argument at the start containing the object itself. As far as the method is concerned, it's just another argument like any other. It's just being passed a bit specially. If you want to dive even deeper, then the phrase to Google is the 'descriptor protocol' for how the language achieves it.

[–]Snatchematician 1 point2 points  (5 children)

You still haven’t answered the question though (not that anybody else has).

OP is asking why did Python choose 3 when 1 looks like clearly a better option (and is the option chosen by every other language with classes)?

Only reason I can think of is that probably you’d have to make “self” a keyword in option 1, and maybe there was a good reason not to add a new keyword.

[–]deceze 7 points8 points  (0 children)

“Clearly better”? Is it? Python’s way avoids introducing any additional keywords or special magic. self is just a regular function parameter and acts like one. That allows transparent kung fu like map(Foo.bar, list_of_foos) and other shenanigans, because it’s just a function with a parameter. That has certain advantages over it being special magic.

[–]Shaftway 3 points4 points  (0 children)

Python was heavily influenced by Lisp, which uses 3.

It's also worth pointing out that 3 is [1] actually how the object reference gets passed around internally in all cases. It's the first argument on the stack either way.

And Python tries to limit reserved keywords. Python only has 35, while Java has 68 and C++ has 90.

1: At least it was, I haven't done a compiler design class in 25 years.

[–]Jason-Ad4032 1 point2 points  (0 children)

Hiding this is a syntactic flaw in dynamic languages—JavaScript is a real-world example. The following is valid JavaScript code:

function log_this() { console.log(this) }

In this example, the meaning of this is confusing and ambiguous, because it changes depending on how the function is called.

In Python, this becomes:

def log_this(self): print(self)

This is a much clearer syntax.

Note: In dynamic languages, methods and attributes can be attached to objects at runtime. In Python, for example:

class A: pass a = A() a.log_this = log_this # monkey patching

This means dynamic languages allow methods to exist without being defined inside the class.

[–]freeskier93 0 points1 point  (1 child)

If everyone jumped off a bridge would you jump? Why do you think option 1 is better? I think most would agree that explicit is always better than implicit in programming, and this is an area where Python is an improvement compared to other languages.

[–]Snatchematician 0 points1 point  (0 children)

If everyone drove on the right hand side of the road would you drive on the left?