When do you use 'self' in Python?
Adding an answer because Oskarbi's isn't explicit.
You use self
when:
- Defining an instance method. It is passed automatically as the first parameter when you call a method on an instance, and it is the instance on which the method was called.
- Referencing a class or instance attribute from inside an instance method. Use it when you want to call a method or access a name (variable) on the instance the method was called on, from inside that method.
You don't use self
when
- You call an instance method normally. Using Oskarbi's example, if you do
instance = MyClass()
, you callMyClass.my_method
asinstance.my_method(some_var)
not asinstance.my_method(self, some_var)
. - You reference a class attribute from outside an instance method but inside the class definition.
- You're inside a staticmethod.
These don'ts are just examples of when not to use self. The dos are when you should use it.
What is the purpose of the `self` parameter? Why is it needed?
The reason you need to use self.
is because Python does not use special syntax to refer to instance attributes. Python decided to do methods in a way that makes the instance to which the method belongs be passed automatically, but not received automatically: the first parameter of methods is the instance the method is called on. That makes methods entirely the same as functions, and leaves the actual name to use up to you (although self
is the convention, and people will generally frown at you when you use something else.) self
is not special to the code, it's just another object.
Python could have done something else to distinguish normal names from attributes -- special syntax like Ruby has, or requiring declarations like C++ and Java do, or perhaps something yet more different -- but it didn't. Python's all for making things explicit, making it obvious what's what, and although it doesn't do it entirely everywhere, it does do it for instance attributes. That's why assigning to an instance attribute needs to know what instance to assign to, and that's why it needs self.
.
When to NOT use the self convention in Python?
There are cases where using self
is not needed.
Off the top of my head:
- when the variable is only used in 1 function, or is created inside a function/method and only used in that function/method
- when the variable doesn't need to be shared between methods
- when the variable doesn't need to be exposed to other classes/scopes/contexts
Another partial answer is that when creating metaclass/factories/composition something like this might make more sense to move away from the convention of using self
like:
class Factory(object):
def __init__(cls, *args, **kwargs):
thing = cls(args, kwargs)
I might be missing some stuff here, but those are what i can think of at the moment.
related:
- https://stackoverflow.com/a/7722353/2026508
- What is the purpose of self?
Classes vs Function: Do I need to use 'self' keyword if using a class in Python?
If you develop functions within a Python class you can two ways of defining a function: The one with a self as first parameter and the other one without self.
So, what is the different between the two?
Function with self
The first one is a method, which is able to access content within the created object. This allows you to access the internal state of an individual object, e.g., a counter of some sorts. These are methods you usually use when using object oriented programming. A short intro can be fund here [External Link]. These methods require you to create new instances of the given class.
Function without self
Functions without initialising an instance of the class. This is why you can directly call them on the imported class.
Alternative solution
This is based on the comment of Tom K. Instead of using self, you can also use the decorator @staticmethod
to indicate the role of the method within your class. Some more info can be found here [External link].
Final thought
To answer you initial question: You do not need to use self
. In your case you do not need self, because you do not share the internal state of an object. Nevertheless, if you are using classes you should think about an object oriented design.
Why do you need explicitly have the self argument in a Python method?
I like to quote Peters' Zen of Python. "Explicit is better than implicit."
In Java and C++, 'this.
' can be deduced, except when you have variable names that make it impossible to deduce. So you sometimes need it and sometimes don't.
Python elects to make things like this explicit rather than based on a rule.
Additionally, since nothing is implied or assumed, parts of the implementation are exposed. self.__class__
, self.__dict__
and other "internal" structures are available in an obvious way.
Why do I need to use self to reference the class variable in a class method?
I defined 'channel_mapping' as class variable, and why do I need to
use 'self' to refer to it?
You can refer class variable via self
(if you ensure it's read-only) and cls
inside the class and it's methods and via classes object or instances from outside of the class.
What is the difference between using cls
and self
? cls
is being used in classmethods since they doesn't require initialization and so instance of the object, and self
is used inside the methods which do require instances of the object.
I thought I should just use
'channel_mapping'
Scopes inside python doesn't work as in C# for example, where you can call class variable by just writing it's name omitting this
where it's redundant. In Python you have to use self
to refer to the instance's variable. Same goes to the class variables but with cls
(or self
) instead.
If you are referencing channel_mapping
you are just referencing a variable from the current or a global scopes whether it exists or not and not from the class or it's instance.
or cls.channel_mapping in the 'process' function?
From the class methods you would want for sure to use cls.channel_mapping
since cls
represents class object. But from the instance's methods, where instead of cls
you have self
you can refer to the class variable using self.__class__.channel_mapping
. What it does is simply returning instance's class which is equal to cls
, and calls class variable channel_mapping
afterwards.
self.channel_mapping
though would return the same result but just because in your code there are no instance attribute called channel_mapping
and so python can resolve your reference to the class variable. But if there would be channel_mapping
variable inside the instance it won't be any longer related to the original class variables, so in that case you would want to keep channel_mapping
read-only.
Summarise, to refer class variable from the class method you would want to just use a cls
and to refer class variable from the instance method you better use self.__class__.var
construction instead of self.var
one.
Also, to define 'channel_mapping' as a class variable like this, or define it as an instance variable in the initializer, is there any thread safety concern in either case?
There are situations when you want to change variables in all instances simultaneously, and that's when class variables comes in handy, you won't need to update every responsible instance variable in every instance, you will just update class variable and that's it.
But speaking of thread safety I'm not really sure will it be simultaneously updated in every thread or not, but self.__class__
will return updated version of a class a soon as it will be updated, so self.__class__
variables will be up to date every time you call it minimizing period within which different threads will use different values of the same variable.
Going up with the initialized variable though, will take longer to update if there are more than one instance so i would consider it less threadsafe.
Related Topics
Restricting the Value in Tkinter Entry Widget
What Is an 'Endpoint' in Flask
How to Add a Question Mark [] Button on the Top of a Tkinter Window
Running a Tkinter Form in a Separate Thread
Why Does Appending to One List Also Append to All Other Lists in My List of Lists
Where to Put Django Startup Code
How to Plot Normal Distribution
How to Open Multiple Webpages in Separate Tabs Within a Browser Using Selenium-Webdriver and Python
How to Highlight Specific X-Value Ranges
Python: Sorting Items from Top Left to Bottom Right with Opencv
Write Dictionary of Lists to a CSV File
Python Split String into Multiple String
Trying to Delay a Specific Function for Spawning Enemy After a Certain Amount of Time
Directing Print Output to a .Txt File
Split a List into Nested Lists on a Value
How to Create an Object for a Django Model with a Many to Many Field