By Readonly


2008-09-16 00:39:55 8 Comments

When defining a method on a class in Python, it looks something like this:

class MyClass(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

But in some other languages, such as C#, you have a reference to the object that the method is bound to with the "this" keyword without declaring it as an argument in the method prototype.

Was this an intentional language design decision in Python or are there some implementation details that require the passing of "self" as an argument?

9 comments

@mon 2019-02-04 05:52:03

As explained in self in Python, Demystified

anything like obj.meth(args) becomes Class.meth(obj, args). The calling process is automatic while the receiving process is not (its explicit). This is the reason the first parameter of a function in class must be the object itself.

class Point(object):
    def __init__(self,x = 0,y = 0):
        self.x = x
        self.y = y

    def distance(self):
        """Find distance from origin"""
        return (self.x**2 + self.y**2) ** 0.5

Invocations:

>>> p1 = Point(6,8)
>>> p1.distance()
10.0

init() defines three parameters but we just passed two (6 and 8). Similarly distance() requires one but zero arguments were passed.

Why is Python not complaining about this argument number mismatch?

Generally, when we call a method with some arguments, the corresponding class function is called by placing the method's object before the first argument. So, anything like obj.meth(args) becomes Class.meth(obj, args). The calling process is automatic while the receiving process is not (its explicit).

This is the reason the first parameter of a function in class must be the object itself. Writing this parameter as self is merely a convention. It is not a keyword and has no special meaning in Python. We could use other names (like this) but I strongly suggest you not to. Using names other than self is frowned upon by most developers and degrades the readability of the code ("Readability counts").
...
In, the first example self.x is an instance attribute whereas x is a local variable. They are not the same and lie in different namespaces.

Self Is Here To Stay

Many have proposed to make self a keyword in Python, like this in C++ and Java. This would eliminate the redundant use of explicit self from the formal parameter list in methods. While this idea seems promising, it's not going to happen. At least not in the near future. The main reason is backward compatibility. Here is a blog from the creator of Python himself explaining why the explicit self has to stay.

@bhadra 2008-11-21 06:28:26

I suggest that one should read Guido van Rossum's blog on this topic - Why explicit self has to stay.

When a method definition is decorated, we don't know whether to automatically give it a 'self' parameter or not: the decorator could turn the function into a static method (which has no 'self'), or a class method (which has a funny kind of self that refers to a class instead of an instance), or it could do something completely different (it's trivial to write a decorator that implements '@classmethod' or '@staticmethod' in pure Python). There's no way without knowing what the decorator does whether to endow the method being defined with an implicit 'self' argument or not.

I reject hacks like special-casing '@classmethod' and '@staticmethod'.

@pankajdoharey 2016-05-01 16:01:06

I think the real reason besides "The Zen of Python" is that Functions are first class citizens in Python.

Which essentially makes them an Object. Now The fundamental issue is if your functions are object as well then, in Object oriented paradigm how would you send messages to Objects when the messages themselves are objects ?

Looks like a chicken egg problem, to reduce this paradox, the only possible way is to either pass a context of execution to methods or detect it. But since python can have nested functions it would be impossible to do so as the context of execution would change for inner functions.

This means the only possible solution is to explicitly pass 'self' (The context of execution).

So i believe it is a implementation problem the Zen came much later.

@Qiulang 2019-04-19 02:52:48

Hi I am new to python (from java background) and I didn't quite flow what you said "how would you send messages to Objects when the messages themselves are objects ". Why is that a problem, can you elaborate?

@pankajdoharey 2019-04-22 15:22:13

@Qiulang Aah, in Object oriented programming calling methods on objects is equivalent to dispatching messages to Objects with or without a payload (parameters to your function). Methods internally would be represented as a block of code associated with an class/object and uses the implicit environment available to it through the object it is invoked against. But if your methods are objects they can exist independent of being associated to a class/object which begs the question if you invoke this method which environment would it run against?

@pankajdoharey 2019-04-22 15:22:42

Thus there must be a mechanism to provide an environment, self would mean the current environment at the point of execution but you could also provide another environment.

@daole 2015-03-31 13:29:09

I think it has to do with PEP 227:

Names in class scope are not accessible. Names are resolved in the innermost enclosing function scope. If a class definition occurs in a chain of nested scopes, the resolution process skips class definitions. This rule prevents odd interactions between class attributes and local variable access. If a name binding operation occurs in a class definition, it creates an attribute on the resulting class object. To access this variable in a method, or in a function nested within a method, an attribute reference must be used, either via self or via the class name.

@vlad-ardelean 2015-07-12 11:18:06

Also allows you to do this: (in short, invoking Outer(3).create_inner_class(4)().weird_sum_with_closure_scope(5) will return 12, but will do so in the craziest of ways.

class Outer(object):
    def __init__(self, outer_num):
        self.outer_num = outer_num

    def create_inner_class(outer_self, inner_arg):
        class Inner(object):
            inner_arg = inner_arg
            def weird_sum_with_closure_scope(inner_self, num)
                return num + outer_self.outer_num + inner_arg
        return Inner

Of course, this is harder to imagine in languages like Java and C#. By making the self reference explicit, you're free to refer to any object by that self reference. Also, such a way of playing with classes at runtime is harder to do in the more static languages - not that's it's necessarily good or bad. It's just that the explicit self allows all this craziness to exist.

Moreover, imagine this: We'd like to customize the behavior of methods (for profiling, or some crazy black magic). This can lead us to think: what if we had a class Method whose behavior we could override or control?

Well here it is:

from functools import partial

class MagicMethod(object):
    """Does black magic when called"""
    def __get__(self, obj, obj_type):
        # This binds the <other> class instance to the <innocent_self> parameter
        # of the method MagicMethod.invoke
        return partial(self.invoke, obj)


    def invoke(magic_self, innocent_self, *args, **kwargs):
        # do black magic here
        ...
        print magic_self, innocent_self, args, kwargs

class InnocentClass(object):
    magic_method = MagicMethod()

And now: InnocentClass().magic_method() will act like expected. The method will be bound with the innocent_self parameter to InnocentClass, and with the magic_self to the MagicMethod instance. Weird huh? It's like having 2 keywords this1 and this2 in languages like Java and C#. Magic like this allows frameworks to do stuff that would otherwise be much more verbose.

Again, I don't want to comment on the ethics of this stuff. I just wanted to show things that would be harder to do without an explicit self reference.

@klaar 2016-04-22 09:19:51

When I consider your first example, I can do the same in Java: the inner class needs to call OuterClass.this to get the 'self' from the outer class, but you can still use this as a reference to itself; very similar to what you do here in Python. For me it wasn't harder to imagine this. Maybe it depends on one's proficiency in the language in question?

@vlad-ardelean 2016-04-23 08:22:52

But can you still refer to any scopes when you're inside a method of an anonymous class, which is defined inside an anonymous class, which is defined inside an anonymous implementation of interface Something, which is in turn defined inside yet another anonymous implementation of Something? In python you can of course refer to any of the scopes.

@klaar 2016-04-25 06:35:45

You are right, in Java you can only refer to the outer class by calling its explicit classname and use that to prefix this. Implicit references are impossibru in Java.

@vlad-ardelean 2016-04-25 07:26:03

I wonder if this would work though: In each scope (each method) have a local variable, that references the this result. For instance Object self1 = this; (either use Object, or something less generic). Then, if you have access to the variable in the higher scopes, you could have access to self1, self2, ...selfn. I think these should be declared final or something, but it might work.

@S.Lott 2008-09-16 00:47:55

I like to quote Peters' Zen of Python. "Explicit is better than implicit."

In Java and C++, 'this.' can be deduced, except when you have variable names that make it impossible to deduce. So you sometimes need it and sometimes don't.

Python elects to make things like this explicit rather than based on a rule.

Additionally, since nothing is implied or assumed, parts of the implementation are exposed. self.__class__, self.__dict__ and other "internal" structures are available in an obvious way.

@Martin Beckett 2009-02-03 23:51:48

Although it would be nice to have a less cryptic error message when you forget it.

@S.Lott 2009-02-04 01:07:38

You can spell it anything (my, this, whatever) and for certain type of class methods, it changes meaning. Not easy to work out your intent and give a "better" message.

@Vedmant 2015-06-05 20:17:09

However when you call a method you don't have to pass object variable, doesn't it breaks the rule of explicitness? If to keep this zen, it have to be something like: object.method(object, param1, param2). Looks somehow inconsistent...

@Vedmant 2015-07-28 13:23:02

@ElmoVanKielmo I don't think so, you pass for example two parameters to function, object.method(param1, param2), but get three parameters def method(self, param1, param2). So first parameter passed implicitly, implicitly != explicitly.

@ElmoVanKielmo 2015-07-28 15:09:17

@Vedmant oh, come on. The concept is so simple and easy to understand. I don't even know why I'm getting into this purely academic discussion. Enormous amount of Python code was successfully developed and it works but now someone doesn't find it natural that the first argument of a method will hold a reference to the object on which the method is called. And there's one more reason for self to be there. In Python you can't use any symbol which is not available in the current scope (except for assignment) so self has to be exactly where it is.

@Simon 2016-07-28 00:32:47

"explicit is better than implicit" - Isn't the "style" of Python built around things being implicit? e.g. implicit data types, implicit function boundaries ( no { }'s), implicit variable scope... if global variables in modules are available in functions... why shouldn't that same logic/reasoning be applied to classes? Wouldn't the simplified rule just be "anything declared at a higher level is available at a lower level" as determined by indentation?

@Simon 2016-07-28 02:50:41

Allow me to answer my own comment... docs.python.org/3/tutorial/classes.html explains it nicely: a variable declared at the high level in a class is available to ALL instances of that class, so to me that's the reason why we need "self" (or whatever you decide to call it) to distinguish. I'd still argue it could be implemented in a simpler way: why not just have a variable "self" (with two underscores either side... i cant get that to display right here) fixed and available with each class to save people putting it in every function?

@Vahid Amiri 2017-03-18 08:28:52

"Explicit is better than implicit" Nonsense detected

@chbaker0 2017-03-22 21:45:39

"In Java and C++, this. can be deduced" This is very imprecise wording. The compiler isn't deducing anything. When it sees a variable name, it does a name lookup starting in the innermost scope and going up to the global or class scope.

@Toskan 2017-08-04 17:00:11

let's face it, it just is bad. There is no excuse for this. It's just an ugly relic but it's ok.

@Victor Noagbodji 2008-09-16 01:15:16

Python doesn't force you on using "self". You can give it whatever name you want. You just have to remember that the first argument in a method definition header is a reference to the object.

@pobk 2008-09-16 08:16:45

By convention, it should however be 'self' for instances or 'cls' where types are involved (mmmm metaclasses)

@Vedmant 2015-07-28 13:29:37

It forces to put self as first param in every method, just extra text that doesn't make much sense as for me. Other languages work just fine with this.

@Mohammad Mahdi KouchakYazdi 2016-09-18 04:39:35

am i right ? always the first parameter is a reference to the object.

@Mark 2016-09-23 11:02:58

@MMKY No, for example with @staticmethod it is not.

@RBV 2017-01-09 20:51:23

"You just have to remember that the first argument in a method definition..." I experimented with changing the word "self" to "kwyjibo" and it still worked. So as is often explained, it's not the word "self" that's important but the position of whatever occupies that space(?)

@Flávio Amieiro 2008-09-16 00:49:26

There is also another very simple answer: according to the zen of python, "explicit is better than implicit".

@Ryan 2008-09-16 00:47:18

It's to minimize the difference between methods and functions. It allows you to easily generate methods in metaclasses, or add methods at runtime to pre-existing classes.

e.g.

>>> class C(object):
...     def foo(self):
...         print "Hi!"
...
>>>
>>> def bar(self):
...     print "Bork bork bork!"
...
>>>
>>> c = C()
>>> C.bar = bar
>>> c.bar()
Bork bork bork!
>>> c.foo()
Hi!
>>>

It also (as far as I know) makes the implementation of the python runtime easier.

@user 2012-05-27 06:20:18

+1 for It's to minimize the difference between methods and functions. This should be accepted answer

@Marcin 2013-07-18 20:25:55

This also at the root of guido's much linked explanation.

@Nishant 2014-01-04 22:55:19

This also shows that in Python , when you do c.bar() first it checks instance for attributes , then it checks class attributes . So you can 'attach' a data or function (objects) to a Class anytime and expect to access in its instance (i.e dir(instance) will s how it ) . Not just when you "created" c instance . Its very dynamic .

@zachaysan 2015-03-01 17:58:06

I don't really buy it. Even in the cases where you need the parent class, you could still infer it upon execution. And equivalence between instance methods and class functions passed instances is silly; Ruby does just fine without them.

@Jonathan Benn 2017-10-23 17:30:33

JavaScript allows you to add methods to an object at run-time, and it doesn't require self in the function declaration (mind you, perhaps this is throwing stones from a glass house, since JavaScript has some pretty tricky this binding semantics)

Related Questions

Sponsored Content

24 Answered Questions

[SOLVED] What is the purpose of the word 'self'?

  • 2010-04-25 20:22:28
  • richzilla
  • 866771 View
  • 1148 Score
  • 24 Answer
  • Tags:   python class oop self

26 Answered Questions

[SOLVED] Does Python have a ternary conditional operator?

10 Answered Questions

[SOLVED] Static methods in Python?

23 Answered Questions

[SOLVED] Creating a singleton in Python

10 Answered Questions

[SOLVED] Why is "1000000000000000 in range(1000000000000001)" so fast in Python 3?

10 Answered Questions

[SOLVED] Does Python have a string 'contains' substring method?

31 Answered Questions

[SOLVED] "Least Astonishment" and the Mutable Default Argument

18 Answered Questions

[SOLVED] What __init__ and self do on Python?

  • 2009-03-09 05:09:51
  • GUIDED BOMB
  • 1122858 View
  • 813 Score
  • 18 Answer
  • Tags:   python oop self

Sponsored Content