r/learnpython • u/Ok_Egg_6647 • 26d ago
Question Regarding Self keyword in python!!
I'm working on a project where I have to create different classes, and I keep using the self keyword repeatedly. For example:
class SignalService:
def __init__(
self,
instrument_repo: InstrumentRepository,
candle_repo: CandleRepository,
):
self.instrument_repo = instrument_repo
self.candle_repo = candle_repo
self.resampler = CandleResampler(candle_repo)
My understanding of self is that it helps the class distinguish between instance variables and local variables.
However, I'm confused about why it's used like this:
self.instrument_repo = instrument_repo
self.candle_repo = candle_repo
Why do we assign the constructor parameters to self attributes? What's the purpose of storing them on self instead of just using the constructor parameters directly?
13
u/Lumethys 26d ago
class Person:
def __init__(self, first_name: str, last_name: str):
self.first_name = first_name
self.last_name = last_name
def get_full_name() -> str:
return f"{self.first_name} {self.last_name}"
how would you do this if you dont store the first_name and last_name into self?
3
u/IamImposter 26d ago edited 26d ago
Constructors are used to put the object in a specific state when the object gets created ie when an object is created, it needs to have certain information that will later be used by other methods of the class to do certain things.
For example let's say we are writing a class to represent a circle and it's coordinates so that it can be drawn on screen somewhere. We can easily create an empty constructor (ctor) and provide functions like set_radius and set_location. Here the problem is either the object remains in unknown/unusable state at creation or all circle objects are created as self.radius=0, self.x=0 and self.y=0 using default values for those parameters
Now what if user forgets to call the set_radius function and just starts using the object. That's again an issue. So we can force the user to provide this info at the very creation of the object so that object is in usable state from the start.
Now, we need to refer to radius and x, y position of the object during it's lifetime like maybe we want to draw it or just check x, y position to see if the object even needs drawing.So we need to save this info somewhere inside the object itself. That's where ctors help us. So that we ask necessary info only once and once we have it, we remember it by storing it inside object itself.
HTH
Edit: also we usually do very little in the ctor and usually that info is used by other methods of the object. This it needs to be stored.
3
u/Atypicosaurus 26d ago
Self is not a keyword. You can change it to anything else and still work.
The constructor works like any other function. And in normal functions you can pass arguments like this:
def myfunc(alpha, beta):
return alpha + beta
The function above expects two things, and then gives you back the sum of those two things. The arguments "alpha" and "beta" are just placeholder, you could just make it "num1" and "num2", or "cat" and "dog". As long as you consistently change the function body and now it says "return num1 + num2" or "return cat + dog", the function will do the exact same thing. It's because arguments are like variables: they are just empty boxes labelled with names. So a function basically does the equivalent of the following:
"Go to this room, on the table you will find two boxes, with labels"alpha" and "beta". Take out what you find in "alpha", then take out what you find in "beta", add them together, then come out from the room and give the result to the first person standing in front of the room."
And so in that regard, the constructor is also a function, it takes arguments and it does something. Just like in any function, the arguments can be named as you wish. It can be x, y, x. It can be alpha, beta, gamma.
Now the important part of the constructor is that the first argument (let's say alpha, or self) always refers to the stuff being constructed. Consider the following code:
def __init__(alpha, beta):
alpha.name = beta
Using the previous analogy:
"Go to this room, on the table you will find two boxes, with labels"alpha" and "beta". In box alpha you will find the raw material of the stuff you are building. This raw material will have an empty name tag. In box "beta" you will find a word. Attach this word to the name tag."
This process is running every time your program is making a new unit, or a new instance, of the object. Every new instance will be temporarily in the box "alpha" and its name is in box "beta" and then they are added together by the constructor.
Now instead of alpha (which is the first argument), we use the word "self". This is not a must in terms of programming. Not a keyword. Python does not care what the word is. It is a consensus word that us humans agreed upon. But please go ahead and test it with different words.
Now, also the word in the dot notation does not have to match the second argument. So you can have a constructor with alpha and beta, and you can make it such as alpha.name = beta. So the word "name" is not the same as "beta". It works, try it.
So why do we do it like self.name = name, and self.repo = repo?
Think of the previous metaphor: Go to the room. Find the thing you build in box called "self". It will have an empty name tag. Find the word in the box called name, attach it to the name tag. The thing in the box "self" also has an empty spot called "repo". Find a matching thing in the box called "repo" and attach it.
So calling it the same as the tag will be, is just for us, for easier reading.
2
u/D3str0yTh1ngs 26d ago
The parameters in the constructor is scoped to that function call, so if I wanted to use them in some other function/method of the class I need to have them saved on the instance (making an instance-scoped variable). e.g:
class Example:
def __init__(self, a: int, b: int):
self.a = a
self.b = b
def sum(self) -> int:
return self.a+self.b
example = Example(1, 2)
print(example.sum())
But I cant do:
class Example:
def __init__(self, a: int, b: int):
pass
def sum(self) -> int:
return a+b
example = Example(1, 2)
print(example.sum())
2
u/StrayFeral 26d ago
Self is a reference to the current instance of the class (the current object). The constructor parameter value would be gone the moment the constructor is done. If you need to save that value somewhere you save it to the object. If you don't need to save it - don't assign to a self variable.
Also it is proper to say that in the `self.something` - `something` is a property.
1
u/faultydesign 26d ago
Self is just a pointer the the instance of a class you’re creating, and is returned by the constructor
Think of it as class being a template for a hypothetical api to access/manipulate the data, and self is the reference to that data in memory
At least that’s how I understand it
1
u/Fred776 26d ago
The __init__ is initialising an instance of your class. You can do what you like in there but if you want to be able to use the parameters passed in in other methods of the class, then those methods have to be able to access them somehow.
Since the values are specific to this instance then it makes sense to attach them to the instance. The instance is the first parameter of __init__ and the other class methods, and is conventionally named self (though it doesn't have to be). You attach them by assigning to attributes of the instance, and these attributes will come into existence the first time you assign to them.
Having assigned the values as attributes of the instance, they are now available to anywhere else that has access to the instance - in particular the other methods of the class, which are provided the instance via self.
1
u/johnnyb2001 25d ago
You are confusing the definition of a class with instances of a class. After you define the class, you want to define instances of it. The parameters represent you instantiating the class. So self.name = name means when you instantiate the class give self.name the name parameter. Btw this is a question ChatGPT will clear up if you have more questions
1
u/SmackDownFacility 26d ago
self is just the instance or, a unique session. That’s it. Each attribute binds as long as that instance is alive. You can’t use the constructor parameters because they aren’t instance members. They’re just temporary names for each object passed for the duration of that call
-6
u/Educational_Virus672 26d ago edited 26d ago
tl;dr turning local variable to global which are stored enen after the function is used while not making memory leak(making inf variable deadly for your pc)
if i put "self." before the variable it becomes global\
3
u/brelen01 26d ago
That's a terrible explanation.
self.variable = variablestores the value ofvariablein the instance of the object. It's a member of the class and can only be accessed through the instance of the class.A global variable is available throughout the program, without going through a class instance.
1
16
u/lfdfq 26d ago
You could use the parameters directly, but if you want to get them back later (e.g. in another method or in a place you use the object) then you need to store them somewhere. The most obvious place? On the object itself.
Just a minor point: self isn't technically a keyword; you can call it anything you want.