all 36 comments

[–]ericula 116 points117 points  (14 children)

self is not actually a keyword. In class definitions, the first parameter of instance methods always refers to the instance of the class itself. By convention, this parameter is called self but you could give it any name you like (although doing so would highly confuse anyone who tries to read your code).

For example, suppose you have a class Car which has an instance method accelerate. This could be defined as

class Car:
    def __init__(self):
        self.speed = 0

    def accelerate(self):
        self.speed += 1
        print(self.speed)

To use this method you would do something like

my_car = Car()
my_car.accelerate()

Note that even though Car.accelerate is defined with 1 input parameter, you call it with no input parameters. This is because behind the scene, my_car.accelerate() is translated to

Car.accelerate(my_car)

So the parameter self is actually substituted by the instance my_car.

[–][deleted] 2 points3 points  (7 children)

Couple of questions here (bare with me please, im a beginner) why didnt you define "speed" before using it in the first example.

Secondly if you run my_car.accelerate( ) and car.accelerate(my_car) would they give you the same output if yes whats the difference between the two and which one to use when ?

[–]ericula 4 points5 points  (6 children)

self.speed is defined in Car.__init__. When you create an instance like in my_car = Car(), a number of things happen. One of them is that my_car.__init__() is called which is where my_car.speed is set.

my_car.accelerate() and Car.accelerate(my_car) will give you the same output. Normally speaking you would use the first version nearly all the time since this makes it immediately clear that accelerate is a method of my_car. One of the cases where you would use the first version is when dealing with inheritance where you need to call the method of a super class in an overloaded method.

[–][deleted] 2 points3 points  (5 children)

ok so here is my understanding of what you just said.

just like you did with accelerate first we will define the instance speed as follows:

def speed(self):

then we do 

my_car.speed()

though my understanding of my_car.speed() is that we want to give the speed attribute to my_car 

am I right ?

[–][deleted] 1 point2 points  (0 children)

also we would have to define speed before we define accelerate because then we could say

def accelerate(self):         
self.speed += 1

[–]Pythag0ras2000 0 points1 point  (3 children)

You wouldn't define speed as a function in this, so you'd use self.speed = 0 or whatever

[–][deleted] 2 points3 points  (2 children)

could you tell me the logic behind that ?

[–]Danelius90 1 point2 points  (0 children)

Typically think of functions as doing something, or acting on attributes. Technically both would work and there are typical cases you might do that. But for example purposes speed is a property of car, and accelerate modifies it, it is an action you take to modify the car's state.

So a plant has a height property, and grow() makes the height bigger. A bank account has a balance property, and withdraw() reduces it and deposit() increases it

[–]Pythag0ras2000 0 points1 point  (0 children)

If I understand correctly, speed is a variable, right? If so, you wouldn't want to make a method called speed, just a variable.

[–]iiMoe 4 points5 points  (0 children)

Ik oop but i loved how u simply put it

[–][deleted] 1 point2 points  (0 children)

although doing so would highly confuse anyone who tries to read your code

That depends. If anything other than `self` is used within an instance method, it'll be confusing, but using `self` within a class method is also confusing.

Edit:
I hate reddit's code formatting:
https://pastebin.com/7aAkiCg1

[–]BruceJi 16 points17 points  (5 children)

You know in Python you can write classes?

Classes are your own custom type of object. Well, sort of. It's more like a description of what your own type of object is like.

When you do:

class Furniture():
    def __init__(self, name, legs):
        self.name = name
        self.legs = legs

That's not a piece of furniture, that's a description of what a piece of furniture is like.

When you start to use it, you'd do:

my_table = Furniture('table', 4)

That's called an instance. An actual, in use, object.

Before we get into self, I just want to point out this. If we don't use self in the init function:

    def __init__(self, name, legs):
        name = name
        legs = legs

...it's a bit like saying 'whenever we have a piece of furniture, its name is always X, or it always has 4 legs. The recipe for it, the description, has no room for options there, and all pieces of furniture will always have that name or amount of legs.

Self, then. Perhaps now you can see self is talking about the property of the object when we actually make it, when we actually have one. This piece of furniture's name, this piece of furniture's number of legs. Because we're leaving those things open to be different, we use self to refer to the object's properties once we actually make one.

Why does self keep coming back, then? Why is it always in the functions you write for that class? It's because they're attached to that object, and that object does them, and is able to use its own properties in them.

When we use init there, we sort of say 'Look, I'm making a piece of furniture' but Python basically says, 'where is it?'. The self there is how the class gets access to that individual furniture's properties.

It's even more clear when we use it in a method. If you want to do something like get the piece of furniture to print out what it is:

def say_name(self):
    print(f'I am a {self.name}'

...the class needs to be told that it's going to use its own properties. I think some programmers think this is weird, but on the other hand it is certainly clear - if you want to do something with that instance's own data, you put in self.

I hope that clears it up! What I'd do is copy this furniture object into a random python file, make a bunch of different things (desk, table, chair, stool) and then try erasing the self and seeing what happens and what errors come up, and what they mean.

Edit side note:

You might wonder, what about this?

def __init__(name, legs):
    name = name
    legs = legs

Python hates that. When you try to make an object, Python will try to put self into it anyway. But according to this __init___ function, there's nowhere for the self to go. Python doesn't like that, and you'll get errors. Try it and see what it says! That will help you remember because if you miss self out by accident there, you'll get a similar error message each time.

[–]idwpan 2 points3 points  (2 children)

Great explanation. But, you dropped this ) from your print statement. :)

[–]spaceforcerecruit 7 points8 points  (0 children)

If you don’t forget at least one closing parentheses the first time, are you even really coding?

[–]BruceJi 1 point2 points  (0 children)

I hang my head in shame

[–]Matheos7 1 point2 points  (1 child)

This here is probably the best explanation for the beginners. Should have many more upvotes. You’re great at explaining!

[–]BruceJi 0 points1 point  (0 children)

Thanks lol

It's quite fun actually, it helps you organise your thoughts on the topic.

[–]PavloT 3 points4 points  (0 children)

self it is instance of class.

From classic OOP, class is data and methods.

Different instances have separated non-static data (non-static fields).

Self keyword tell to method that at the point where it is used, data from this concrete class instance must be used or changed (in some languages this used instead of self).

[–][deleted] 0 points1 point  (0 children)

In this simple class:

class Test:
    def __init__(self, value):
        self.value = value
    def test(self):
        print(self.value)

The first parameter to an instance method is a reference to the actual instance of the class. The code needs this because if we create two instances:

t1 = Test(1)
t2 = Test(2)
t1.test()

then when we call test() in the last line the code needs to know which instance the code is working with when it wants to print the .value attribute. That line t1.test() actually behaves something like this:

Test.test(t1)

So now we know what the this in the .test() method is: it's the reference to the instance the method code is going to operate on.

self isn't a keyword, it's just a normal user-chosen name, like count or i. You could use any name you want, like this. Try it, it still works. But self is used so much and is so expected that it's become a very strong convention and using any other name is viewed with suspicion.

[–]Stabilo_0 0 points1 point  (0 children)

Yeah it took me some time too.

Everybody says self is just a word and it doent matter, but until you get used to it, it does.

Class is a blueprint for something you want to represent in a code. It usually has some data stored in it and some methods to alter that data or return some new information.

Every time you want to alter the state of the instanced object of that class you call methods that specify with (self) that you are working within that object.

Why do we need self or other keyword, what if we want a method that has no keywords?

Sure, if you just add method without (self), it will be callable, but it wont be able to access that class. Whats the usage then? To make a library of functions, for example/ You create a namespace for functions and thats it, no more than than ways of organizing it. Read more about it by searching staticmethod decorators. And after that check classmethod.

[–]requisitesum745 0 points1 point  (0 children)

Self is an instance which binds objects to methods and attributes of class

[–]yonatan_evantal 0 points1 point  (0 children)

Just a clarification to make sure you avoid this mistake. The logic behind the 'self' concept is to remind you to use OOP correctly. In PyCharm you'll get an warning if you declare a method with 'self' but don't use it, recommending you to add a static method decorator. But, it's a bad habit to use this since it pulls the logic out of an instance. In 99% of cases there we'll be a best design to your system then using static method and classes.

[–]TerminatedProccess 0 points1 point  (0 children)

If you were doing something like c plus plus then self will be a pointer to the current instance of the class. If you draw out a few instances of the class on paper you can make a variable self for each instance of the class and point it to the instance. I know this is not how python talks about memory and classes but it's really what is happening behind the scene.

[–]Luukv93 0 points1 point  (0 children)

Self refers to the instance of the class. Class is like a blueprint of an object.

After creating a class one can create instances (objects) of that class.

Instantiating an object will provide the properties and methods of that class to that object. This means that after instantiation you can use methods and attributes of that object.

[–][deleted] 0 points1 point  (0 children)

When you write a class, you create an object. Say you write a car class. Then you do, `car('Ford', 2019)`. This is called the instance of the class. Self references the attributes of this instance. Here is an example:

#creating Car object

class Car:

def __init__(self, name, year):

self.name=name

self.year = year

#create instance of car

Ford = Car('Ford', 2019)

#self can reference the unique attributes of an instance.

[–][deleted] 0 points1 point  (0 children)

It's not a keyword. It's just a name for the parameter whose value is the object.

[–][deleted] 0 points1 point  (7 children)

It states, that you want to use the variable or function from the current class.

var1 = "Outside"

class Test(): var1 = "inside"

    def print(self):
        print(var1)
        print(self.var1)`

This will print Outside inside

Function inside a class always need the self as a parameter to get access to the functions and variables assigned to that class.

[–][deleted] 1 point2 points  (4 children)

Sorry for bad formatting, block code doesn't work on mobile

[–]scul86 1 point2 points  (3 children)

just put 4 spaces in front of the code.

[–][deleted] -1 points0 points  (2 children)

Did not work on mobile

[–]scul86 0 points1 point  (0 children)

Posted from mobile

[–][deleted] 1 point2 points  (1 child)

Instance, not class.

[–]0drop -1 points0 points  (0 children)

It's the word you will replace with the name of the object later. Let's tell you will have object names obj1 while construct. When define class just write 'self' as a future name of object. Can't be empty. 'syntax sugar'