That's how it is. Python objects are actually bags of properties (attributes). Some of them are regular values, while others are functions. They have no special binding to the class, except for the attribute of its instances. The method invocation syntax is just a little sugar, taking care of passing the first parameter to you. Actually, methods are just simple functions, and you can name them as such by explicitly passing the first parameter.
I do not know why this choice was made, but I believe that this is due to the fact that you can assign free functions as attributes to existing objects, and then call them methods; without an explicit self parameter, this will lead to even more confusion.
The mechanism is similar to Javascript, only in Javascript the this argument is implicitly passed as a local variable named this without an explicit parameter, whereas in Python you can choose the name your own sympathy through the explicit first parameter - self not a keyword, but just a convention. This difference also means that you can use functions as methods more easily - the javascript function that uses this will break if used outside the context of the object (more precisely, in the context of the default object, usually window ), but in Python, you can pass matching object as the first parameter.
Note that other OOP differences (Java, C ++, etc.) also pass the self / this parameter to your method, but they do it implicitly, and this does not appear as an explicit argument. These languages do not allow methods to be called as free functions, although (and vv., You cannot use a free function as a method).
What this is called __init__ : there is at least one advantage, namely that you can rename a class without renaming the constructor. This makes refactoring easier and less error prone. BTW, Python is not alone in this - PHP uses __construct , although constructors with a class name are also supported, but no longer recommended.