Why do we have to use the attribute self as an argument in the methods?

Asked

Viewed 17,530 times

20

I watched a video class where it is said that every method is required to pass the parameter self in the method definition, as in the example below:

class Complex(object):
    def __init__(self, real, imag):
        self._real = real
        self._imag = imag

This example I took back from here. The only explanation I found on this page was this. But I didn’t understand what the author meant.

The first argument of the method is always referenced at the beginning of the case. By convention, the first argument of the method always has the self name. Therefore, the attributes of self are instance attributes class.

In Java, which is a language I’m already familiar with, there is no need for that. Does anyone know why this obligation in Python?

  • 2

    Only yesterday this was answered: http://answall.com/questions/176250/qual-a-forma-correta-de-chamar-m%C3%A9todos-em-python/176252#176252 , Wallace’s answer explains this

  • 1
  • 1

    @Miguel Thanks for the reminder. Although Wallace’s answer was correct, I thought it was kind of superficial. I would like to understand the real need, the reason besides saying that it belongs to the method. Since in other languages there is no such need.

  • 1

    @Nottherealhemingway thanks, it seems to be a great reference. I will read it calmly soon. If ngm has replied I will try to draw up a reply based on what I have learned and post here.

  • If it helps, put your conclusions about your question here as an answer and mark your considerations as an answer, please. This will help those who have the same question and the question will be answered. In addition we will have the beginning of a documentation for the problem (I think that’s the goal).

  • 1
Show 1 more comment

3 answers

19


Only one convention to make explicit the object instance within the class.

The author of the language define (in question 4.21) self as follows:

Self is merely a Conventional name for the first argument of a method -- i.e. a Function defined Inside a class Definition. A method defined as meth(self, a, b, c) should be called as x.meth(a, b, c) for some instance x of the class in which the Definition occurs; the called method will think it is called as meth(x, a, b, c).

I will create a fictional story that is just a joke to illustrate and try to give an understanding that makes more sense than just a convention as explained by the author.

Suppose I want to write several common functions for a certain object, which in the case of Python can be a simple dictionary.
Thus, when calling each function I wrote, I would have to pass to this function this object and then the parameters of the function itself. Example:

item = {'qt': 10, 'nome': 'Banana', 'preco': 12.20}

def Desconto(objeto, percentual):
  objeto['preco'] = objeto['preco'] * (percentual / 100.0)

And to call the function:

Desconto(item, 10)

Let’s say that I assemble a number of functions that work on top of the same type of object. We can say that I created a class functions. For organisational purposes we will agree that the name of the functions shall become NomeDaClasse.NomeDaFunção(Objeto, Param1, Param2, ...). I’d have something like:

def MinhaClasse.Funcao1(Objeto, Param1, Param2, ...)
   ...
def MinhaClasse.Funcao2(Objeto, Param1, Param2, ...)
   ...
def MinhaClasse.Funcao3(Objeto, Param1, Param2, ...)
   ...

Now, whenever I want to call a function just identify the class and know that the first parameter is always an object of a certain type that that class of functions understands.

If I agree that in my source code I can write this set of functions in a different way, for example, not to repeat the class name in the function name, I will put it like this:

class NomeDaClasse ()
   def Funcao1(Objeto, Param1, Param2, ...)
     ...
   def Funcao2(Objeto, Param1, Param2, ...)
     ...

When I wanted to call the function of this class, I would continue to do:

NomeDaClasse.NomeDaFuncao(Objeto, Param1, Param2, ...)

But how I created a very similar way to the class structure of OO, then I could find a way to create a way to pass the attributes of my object on an initializer, which I will also agree with a very different name, for example, __init__ and through it I pass the attribute values of my "object" and create a single instance of that class. Everything will look very much like the classes and objects of OO.

I will also agree that I can call the functions of my object with a simpler syntax, for example:

MeuObjeto.MinhaFuncao(Param1, Param2, ...)

Since I simplified everything but I don’t want the programmer to know that there are things implicit in these conventions of mine, I will keep in the signature of the functions within the class a special name, which I will call self to specify the parameter that is the object of my class. When calling, internally my compiler would do the following:

MeuObjeto.MinhaFuncao(...) => MinhaClasse.MinhaFuncao(MeuObjeto, ...)

So I made it easy for the programmer who can use a syntax very similar to the syntax of OO and I’ll make it explicit to those conventions I’ve made, leaving the name self within the signature of class methods.

  • Python has classes and object orientation from the start - the first public release, version 0.9.0, in 1991 was already OOP

  • 1

    @jsbueno You are right I will edit the answer to remove this and put the definition of what is "self" by the language author himself and make it clearer that the analogy I created is fictitious.

12

If you follow the Python zen you will see that in Python: Explicit is better than implicit. And this is taken very seriously in all language and in all proposals for novelties for her.

The same way you need to pass self in the instance methods, you also cannot omit the self. when accessing the methods or instance variables. You can see this also by the opposite logic: languages like Java and C# invented this reserved word this which is nothing more than a hidden argument to a function that has been declared as method, representing the current object.

These choices in the Python language design made it possible not to create a reserved word to represent this implicit argument within the methods. This way the methods work exactly the same as all other functions. Even you don’t need to call the first argument self. You can be whatever you want.

Then take a look at history behind class syntax.

  • +1 for The Zen of Python

7

At first self is just one parameter like any other. In it you receive an object and then through this variable, after all every parameter is also a variable, you will access the members of that object.

What is different in the language is that in the method call there is a treatment for the object to be passed as this parameter.

Think that methods do not actually exist, what exists is a function with a first parameter that is special. This parameter always takes the name of self.

So if we have a class called Classe and an instance of that class is called so

objeto.metodo()

actually is

Classe_metodo(objeto)

objeto is the argument being passed and the parameter self in metodo() will receive this instance. The language trick only occurs in what has been shown above, the rest is all the same.

class Classe(object):
    propriedade = 0
    def metodo(self):
        print(self.propriedade) #se tiver só propriedade aqui seria uma variavel local
        
objeto = Classe()
objeto.propriedade = 10
objeto.metodo()

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

Note that self is a convention that all good Pythonist follows, but in fact you could put whatever you wanted to name the first parameter of the method, this, obj, abobrinha, etc..

Browser other questions tagged

You are not signed in. Login or sign up in order to post.