I took a closer look at why Python self is needed

What is self, which is the first argument of a class method?

When studying a class, I think the first huge barrier is ** Why should I use self as a method argument? **.

I think that it is often convinced that it is a rule, so let's put it in, but I think that it is not convincing for beginners who want to understand the structure firmly and move on.

I've just started studying Python myself, but I've finally stopped learning how to use selt. This is because I thought, "Tell me why you use it!" And I don't want to proceed with it being moody.

Probably, it is a rule, so I don't think it will be too difficult to proceed, but I want to understand it properly, so I summarized the learning contents. I am also one of the beginners, so I tried to make the description as much as possible so that the beginners could understand it.

For this study, the explanation of this site was the most convincing, so I summarized it as a reference.

Check if it is really useless if you do not enter self

First of all, I thought that I didn't need self, so I wrote the source without using self.

class Person:
    def __init__(name):
        p_name = name
        
    def introduce():
        print("I" + p_name + "is.")

player = Person("Taro")
player.introduce()

① When creating the instance "player", pass the argument "Taro" to the class (2) "Taro" is assigned to the p_name variable by the constructor (initialization / processing in init). ③ The introduce method outputs "I am Taro" (should)

If you try this, the result will be:

Traceback (most recent call last):
  File "Main.py", line 25, in <module>
    player = Person("Taro")
TypeError: __init__() takes 1 positional argument but 2 were given
(Exit status: 1)

The process doesn't seem to be wrong, but for some reason I'm getting an error. .. .. player = Person ("Taro") It seems that an error has occurred in the processing of. You should have passed the arguments to the class properly.

** However, if you look at the error message here, you will find it interesting. ** **

TypeError: __init__() takes 1 positional argument but 2 were given

What does this mean? ** "Why are you specifying two init methods when you can only take one variable?" ** It is said that.

No, you only have one variable, right? What are you talking about? Is it a Python bug?

On the other hand, rewrite the code according to the "rules" and execute it.

class Person:
    def __init__(self,name):
        self.name = name
        
    def introduce(self):
        print("I" + self.name + "is.")

player = Person("Taro")
player.introduce()

When I try to do this.

I'm Taro

It seems that it is output correctly. The difference between the two codes is whether you include self or not, but if you include self, it works correctly. I'm still not sure, so please refer to this site to find out why the processing is different like this. thinking.

Apparently there are hidden arguments

In the processing of the code that does not specify self earlier TypeError: __init__() takes 1 positional argument but 2 were given I got an error saying, but what was the meaning of this?

** "Why do you specify two init methods when you can only take one argument?" **

It was that. In other words, if you return the opposite of this,

** "If there are two arguments of the init method, it can be processed without any problem" **

In other words, in the specification method of player = Person ("Taro "), two arguments are actually specified, but in the init function, only one argument, name, is specified. Therefore, an error has occurred.

The key to understanding self is that when you specify player = Person ("Taro "), you are passing ** another hidden variable **.

So, in the description of the init function, it seems good to specify def __init __ (nazo, name). There is a mysterious argument that I do not understand well, so try specifying the argument "nazo".

class Person:
    def __init__(nazo,name):
        nazo.name = name
        
    def introduce(nazo):
        print("I" + nazo.name + "is.")

player = Person("Taro")
player.introduce()

When I try to do this.

I'm Taro

that?

It's not self, but it has passed. Yes, it looks like it doesn't have to be ** self **.

What we have learned so far is that there is a mystery argument and that it can be processed by entering the mystery argument. And the argument doesn't have to be self.

It smelled like I could reach it soon.

What exactly is being passed as an argument

As an example, consider a function that capitalizes the letters "python". The function to capitalize is in the str class (a class originally prepared in Python) and can be processed by using the upper function.

The upper function is defined in the class as def upper (object): and can be called as str.upper (object).

string = "python"
print(str.upper(string))

If you do this, you will get the output PYTHON.

However, no one would convert to uppercase with such a statement. Perhaps many would write code like this for the process of capitalizing.

string = "python"
print(string.upper())

If you do this, you will still get the output PYTHON.

According to the explanation of here, it seems that the description ** string.upper (string) is hard to see in python, so let's stop it. You can omit the argument string, but behind the scenes, let's assume that the argument is taken properly **.

Now, what is the omitted argument is the string itself, that is, "I = self".

The point is that you can omit the object's arguments when using the method from the ** object. However, it's okay to omit it, and I'll secretly get it as an argument behind the scenes! It seems that python has a rule of **.

What I want to say is ** When the player instance created earlier uses the method called introduce, it should be written as player.introduce (player), but the argument player is omitted. Then you can write player.introduce (). Instead, it means that it is omitted in the description, and the argument itself has not disappeared, so the class will get the argument as "self" without permission **.

That is to say, in the same way, if you describe the init method for convenience when using it (it is executed arbitrarily because it is a constructor), it should be ** player.init (player," Taro "). It must be **, but it can be omitted in the same way, so on the instance side, you can write player = Person ("Taro"). Instead, the class has to get the omitted argument, so the class needs to set "self" as an argument.

Based on this, let's look at the Person class again.

class Person:
    def __init__(nazo,name):
        nazo.name = name
        
    def introduce(nazo):
        print("I" + nazo.name + "is.")

player = Person("Taro")
player.introduce()

What you can say from this source code is ** Do you want to use the init method of the Person class? Then you can omit the argument "you (self)", but since it is only allowed to be omitted, the class will get the argument (self) properly **.

I think an easy-to-understand example is "Python class shop allows face paths for instances".

When an instance called `player enters a class shop, you normally have to write your name on the list, but it is supposed to be" Because you are a familiar person, you can use a face pass! " .. However, as a class shop, I would like to mention that the player came for sales management. ``

I finally got the answer, ** self is the instance itself **. Normally, you have to tell the name (player) properly to use it, but since face pass is allowed, you do not have to write it one by one. However, I want you to write it as a real rule, so in the class, self is set as an argument.

Finally, I would like to check the source code again. I wrote "nazo" earlier, but since the instance itself is an argument, "self" is preferable.

class Person:
    #If you want to use the init function, you can use the face path, but I'll write the name here.
    #If you don't, you won't know who you are.
    def __init__(self,name):
    #"you(self)of"I'll write the name here.
        self.name = name
     
    #It's a face pass, so you can use it without permission, but I don't know who used it, so I'll write down my name here.
    def introduce(self):
        print("I" + self.name + "is.")

player = Person("Taro")
player.introduce()

Afterword

It may be difficult to understand because it is a beginner, but I think it's okay if you remember it with such an image. If you want to know a little more, [this site](https://python.ms/self/#%E7%96%91%E5%95%8F-%E3%81%AA%E3%82%93%E3 % 81% A7% E6% 98% 8E% E7% A4% BA% E7% 9A% 84% E3% 81% AB-self-% E3% 82% 92% E6% 9B% B8% E3% 81% 8F% E3% 81% AE% EF% BC% 9F) is good, but it is difficult for beginners, so it seems better to read it again after reaching intermediate level or higher. I could understand half, but I didn't understand half yet.

I hope that even one person learning Python will read this article and not stumble on himself.

Recommended Posts

I took a closer look at why Python self is needed
I took a quick look at the fractions package that handles Python built-in fractions.
I thought about why Python self is necessary with the feeling of a Python interpreter
Why Python slicing is represented by a colon (:)
I learned Python with a beautiful girl at Paiza # 02
I took a look at the contents of sklearn (scikit-learn) (1) ~ What about the implementation of CountVectorizer? ~
Why is the first argument of [Python] Class self?
Take a closer look at the Kaggle / Titanic tutorial
Why I chose Python
Take a look at the Python built-in exception tree structure
Python list is not a list
I made a python text
What is a python map?
Take a look at the built-in exception tree structure in Python 3.8.2
I did a lot of research on how Python is executed
i! i! ← This is a mathematical formula
[Go] Take a look at io.Writer
I made a Line-bot using Python!
Take a look at Django's template.
I made a fortune with Python.
I took Progete's Python Learning Course I
I made a daemon with Python
What is the XX file at the root of a popular Python project?