The article "Unlock the 4 Mysteries of self in Python" elucidates the concept of self in Python classes, explaining its purpose, usage, and common misconceptions.
Abstract
The article provides a comprehensive guide to understanding the self keyword in Python, which is often a source of confusion for beginners. It clarifies that self refers to the instance of a class that calls a method, and it is automatically passed to instance methods without needing to be explicitly provided. The author dispels the notion that self is a keyword in Python, demonstrating that it can be used as a variable name outside of class method definitions. Additionally, the article emphasizes the necessity of self in instance methods, distinguishing it from class and static methods where self is not required. Through examples and explanations, the article aims to demystify self for Python learners and enhance their grasp of object-oriented programming in Python.
Opinions
The author believes that understanding self is crucial for mastering Python, as it is a fundamental aspect of object-oriented programming within the language.
The article suggests that the implicit nature of self's passing to instance methods can be puzzling to those new to Python, but it is a design choice that simplifies method calls on instances.
It is the author's view that the convention of using self is widely accepted and deviating from it, while syntactically permissible, is discouraged as it may lead to confusion among other developers.
The author implies that a deeper understanding of Python's object model, including the nature of bound methods and the role of introspection functions, is beneficial for unraveling the mysteries surrounding self.
By unlocking the mysteries of self, the author anticipates that readers will gain confidence in using classes and methods in Python, leading to more effective programming practices.
With little exception, every structured Python course has a lecture on classes — one of the fundamental building blocks for Python and any other object-oriented programming language.
When you’re learning it through some examples, you’ll notice that many functions defined in a Python class have self as their first argument. For instance, in the code snippet below, we declare a class called Student, and its greet() method has self as its first argument. What’s more, the body of the function doesn’t use self at all, which is the first mystery to many beginners. What on earth is it?
Strangely, when we use this function, we don’t set anything to the self argument, which is another mystery that bothered me. When I explored more about self in Python, I found more mysteries but was finally able to figure out what it is. Thus, in this article, I would like to share these universal mysteries among some Python learners. More importantly, let’s unlock these mysteries together.
Before we start to address this mystery, we need to understand two basic pertinent concepts: class and instance. Certainly, resolving all these mysteries requires additional knowledge beyond classes and instances, which I’ll clarify while we’re moving forward. If you know both well, you can skip the next paragraph, which is just a brief overview of these two concepts.
Creating a Python class is declaring a new type of object, which provides a mechanism of bundling data and functionality together. In the example above, we created a class called Student, using which we created an object of this Student type called student. This object is called an instance of the Student class. Besides, the class can provide specific functionalities called attributes in general, such as the greet() function in the example. We use three introspection (see my previous article on Python’s introspection) functions (type(), isinstance() and hasattr()) to check the relevant information.
Without going too far, I can tell you that the self argument in the greet() function is the instance student in the example above. More generally, it is the instance that calls this function. Here’s the supporting evidence:
In the code above, we modified the greet() function by asking it to show us the memory address of the self argument using the introspection id() function. As you can see, the self argument and the instance student are the same object, as they have the same memory address.
Unlocked mystery:The self argument in the function declaration refers to the instance object that calls the function.
2. Why Don’t We Need to Set It in the Function Call?
Continuing with the example shown in the last section, when we use the instance student to call the greet() function, this function is generally known as an instance method — a function that is available to an instance of a certain class. However, if we check the type of this attribute, something different will be shown.
As you can see above, the instance student’s greet attribute is known as a bound method. Specifically, it’s bound to the greet attribute of the class Student.
To understand precisely what this means, let’s see the code below:
>>>Student.greet(student, 'John')
Good Morning, John
Put together with the example at the beginning, you may have noticed three things in this code:
The caller of this function is the class Student — not the instance student.
Both the self and name arguments are set in this call, unlike the initial function call made by the student where the self argument is omitted.
Both function calls have resulted in the same output. They’re essentially using the same function.
By realizing these pieces of information, you may have already guessed what happened behind the scenes when we use the instance student to call the greet() function.
Calling the greet() method.
As shown in the diagram above, when the instance student calls the greet(‘John’) method, this function call is processed by the interpreter as the class Student sending the caller (i.e. the instance student) and the name argument (i.e. ‘John’) to the greet(self, name) function, which prints out “Good Morning, John.”
For interested readers, here are a few things to know that can help you have a more in-depth understanding of this mystery. When a Python class is created, its declared functions are the attributes of the class (known as function objects). In other words, the class “owns” these functions. Instances of the class won’t directly implement these functions. Instead, they’ll have the same attributes (a.k.a. instance methods) that are bound to the corresponding functions implemented in their class.
Unlocked mystery: The instance object will be set to the self argument automatically when it’s calling the instance method.
3. Is self a Keyword?
It appears that in all these defined functions, we use self as their first argument. Someone may have mistakenly thought that self is a keyword that is reserved by Python for these use cases. However, this is not true. Please see a simple example below:
As you may know, def and class are keywords in Python that we can’t use as variable names. However, we can use self as a variable name outside the context of defining a function, which indicates it’s not a reserved keyword in Python.
Unlocked mystery: The word self is not a keyword in Python.
4. Do We Have to Use self in These Function Declarations?
In the examples above, we repeatedly refer to the greet() function. As we have discussed, we implemented this function as an instance method such that it can be used by all instances of this Student class. In this case, self is required. See below for some evidence:
Here’s some analysis. As covered previously, when the instance teacher calls the say_hello() method, what’s happening is executing the Teacher.say_hello() function with the instance object teacher and ‘John’ set to the function call. This is why the error says “2 were given.” This is in contrast with the definition of the function, which only takes one argument (name).
However, there are two more things related to this mystery that you may want to know:
Although declaring an instance method requires the inclusion of the self argument, it doesn’t have to be named self. The use of this name in this scenario is just a convention that every Python programmer can appreciate. Here’s an example showing you that it can be named something else without causing any problems. Although it’s syntactically correct, it’s not recommended, as it only confuses other Python programmers:
When we declare other functions, like class and static methods, we don’t need to use the self argument. A clear explanation of class and static methods can be the topic of a future article. But what I can show you here is that when we declare a class method, the function does have something similar to the usage of self in instance methods, which is conventionally called cls referring to the class object itself. It has nothing to do with specific instances. An example is given below:
Unlocked mystery: The self argument is required for declaring instance methods, but not for class and static methods.
Takeaways
These four mysteries represent some common problems among Python programmers regarding self in Python. After reading this article, I bet that you have a better understanding of self and its intended usage.
Thank you for reading this article and enjoy coding in Python.