self is the explicit first parameter; binding happens through the descriptor protocol, not a keyword
self is just a conventional name for the first parameter of an instance method. It is not a keyword. When you write obj.method(x), Python first looks up method on the class, finds a function object, and because functions implement get, it returns a bound method that already has obj as the first argument. So obj.method(x) is effectively Class.method(obj, x). Python requires the first parameter to be explicit for readability and because functions are plain objects; there is no hidden this. This also means you can call the underlying function directly with an explicit instance, which is what super() and unbound-method patterns exploit.
self is not special to the parser; it is special only by convention. Naming it cls in a classmethod is also convention.
Binding happens via functions being descriptors: function.get(instance, owner) returns a method object.
Trade-off: explicitness makes it clear what is bound, but it adds visual noise and is the most common source of TypeError: missing 1 required positional argument.
Common mistake: thinking you must name it self. You can name it anything, but doing so breaks readability and tooling assumptions.
Common mistake: calling Class.method(x) on an instance method and forgetting that you must pass the instance explicitly.
Version note: unbound method objects from Python 2 were removed in Python 3; functions are simply descriptors now.
0-2 years experience
2-5 years experience
5-8 years experience
8+ years experience