When working with Python classes and objects, you might encounter the following error:
NameError: name 'self' is not defined
This error occurs because Python can’t find the definition of the self
variable that you called in your code.
There are two possible scenarios that cause this error:
- You use
self
as the default value for an argument - You access
self
from a static method
This tutorial will show you how to fix the error in each scenario.
1. Using self as the default value for an argument
Suppose you have a class named Person
with the following definition:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
Next, you created a method named greet()
inside the class defined as follows:
def greet(self, name=self.name):
print(f'Hello! My name is {name}')
After that, you created an instance of the class and called the greet()
method:
joe = Person('Joe', 22)
joe.greet()
You’ll get the following error:
Traceback (most recent call last):
File "main.py", line 1, in <module>
class Person:
File "main.py", line 6, in Person
def greet(self, name = self.name):
^^^^
NameError: name 'self' is not defined
This error occurs because the self.name
attribute is used as the default argument for the name
parameter.
In Python, default arguments are evaluated when Python runs the code for the first time. That is, when Python put your method definition in the memory and makes it available for calling.
But the self
object is only available when the method is actually called. This is why you can’t use self
as a default argument.
To resolve this error, you need to assign self
to the parameter in your method body. A common pattern is to use None
as the default argument, and change it inside the function as follows:
def greet(self, name=None):
if name is None:
name = self.name
print(f'Hello! My name is {name}')
Now you can run the greet()
function without receiving the error:
joe = Person('Joe', 22)
joe.greet() # Hello! My name is Joe
But the drawback of this solution is that you can’t explicitly set the name
parameter to None
because it will just get reassigned to self.name
.
If you have many parameters that use self
attributes as the default arguments, then you need to create many if
statements as shown above.
It looks ugly and inconvenient, but there’s no other way considering how Python evaluates the default arguments.
2. You access self from a static method
As you probably know, Python implicitly passed the self
object as the first argument anytime you called a class method.
A static method is an exception to this rule because it was intended to work with class attributes instead of class instances.
Suppose you create a Person
class with a static method called greet()
as shown below:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@staticmethod
def greet():
print(f'Hello! My name is {self.name}')
Next, you create a new instance of the class and call the greet()
method as follows:
joe = Person('Joe', 22)
joe.greet()
Output:
Traceback (most recent call last):
File "main.py", line 11, in <module>
joe.greet()
File "main.py", line 8, in greet
print(f'Hello! My name is {self.name}')
^^^^
NameError: name 'self' is not defined
When you declared a method as static in Python, the self
object is not passed implicitly, so the error occurs.
To resolve this error, you need to remove the @staticmethod
modifier above the method name and define the self
object as a parameter of the method:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
print(f'Hello! My name is {self.name}')
Now you can access self
inside the greet()
method without receiving the error.
Conclusion
The NameError: name 'self' is not defined
occurs in Python when you try to access the self
object from a place that doesn’t have the definition of self
.
The most probable cause for this error is that you use the self
attribute as the default argument of your method’s parameter, or you try to access self
from a static method.
Keep in mind that this error doesn’t appear when you didn’t specify self
as the first parameter of a method.
For that, you’ll get another error saying TypeError: method takes 0 positional arguments but 1 was given.
I hope this tutorial is helpful. Happy coding! 👍