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

10

I watched a video lesson where it is said that every method is required to pass the self parameter 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 will remove from here . The only explanation I found on this page was this. But I did not understand what the author meant.

  

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

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

    
asked by anonymous 10.01.2017 / 19:44

3 answers

9

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

Python is a language that was initially created with the functional paradigm. Over time, support has been placed for object-oriented code, which is another paradigm. At the time the authors decided that it should be explicit the passage of the object to which belongs the function that is being called when the function belongs to a class because the focus of the language were the functions. So they agreed it would be the first parameter and the name would be self .

I'm going to create a fictional story of what the Python authors think would be, but it's just a joke to illustrate and try to give an understanding that makes more sense than just a convention.

Suppose I want to write several common functions for a certain object, which in the case of Python can be a simple dictionary. That way, when calling each function I wrote, I would have to pass that object to that function and then the parameters themselves of the function. 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 mount a series of functions that work on the same type of object. We can say that I created a class of functions. For organization effect we will agree that the function name becomes NomeDaClasse.NomeDaFunção(Objeto, Param1, Param2, ...) . I would have something like this:

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'll put it like this:

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

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

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

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

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

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

As I have simplified everything but I do not want the programmer to know that there are things implicit in these conventions, I will keep in the signature of the functions within the class a special name, which I will call self to indicate the parameter that is the object of my class. When making the call, internally my compiler would do the following:

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

So I made it easier for the programmer to use a syntax that looks very similar to the OO syntax and how my language is functional, I'll make it explicit to those conventions I've made, leaving the name self within the signature of functions within the class.

    
10.01.2017 / 21:02
5

If you follow 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 of news for her.

Just as you need to pass self to instance methods, you also can not omit self. when you access instance methods or 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 was declared as method , representing the current object .

These choices in the Python language design have made it unnecessary to create a reserved word to represent this implicit argument within the methods. In this way the methods work exactly like all other functions. You do not even need to call the first self argument. It can be whatever you want.

Then read the story behind the syntax of classes .

    
10.01.2017 / 21:35
2

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

What's different about language is that in the method call there is a handle to the object being passed as this parameter.

Think of which methods do not really exist, what exists is a function with a first parameter that is special. This parameter is always named self .

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

objeto.metodo()

It's actually

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()

See running on ideone . And No Coding Ground . Also put it on GitHub for future reference .

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

    
13.02.2017 / 13:05