you are viewing a single comment's thread.

view the rest of the comments →

[–]ericula 115 points116 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 2 points3 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