Every Python class tutorial shows self in the first line of every method, and beginners are often told "just include it." This tutorial explains what it actually does, why every method needs it, and how to use it with confidence.
Contents
When you write a class in Python, every method that operates on an instance needs a way to refer to that specific instance. That is the entire job of self. It is not magic — it is a parameter like any other, and Python fills it in for you automatically every time you call a method on an object.
If you are still getting comfortable with Python classes in general, the guide to using classes in Python is a good companion read before continuing.
What self Is and Why It Exists
When you call a class in Python — for example buddy = Dog() — Python creates a new object from that class. That object is called an instance. You can create as many instances as you like from the same class: buddy and rex are both Dog instances, but each one is its own independent object with its own separate data.
That separation is exactly where self comes in. When a method runs, it needs to know which instance's data to read or change. self is the parameter that carries that information — it is a reference to the specific object the method was called on.
Consider those two Dog instances. If you call buddy.bark(), Python needs to know that bark() should act on buddy — not on rex or any other dog. It does that by automatically passing buddy as the first argument to bark(). The method's first parameter — called self by convention — receives that argument.
self is not a keyword. Python does not reserve it. The name self is a convention followed throughout the entire Python ecosystem — every developer, linter, and IDE expects it. Always use self.
Here is the simplest class possible that shows self in action:
class Dog:
def bark(self):
print("Woof!")
buddy = Dog()
buddy.bark() # Python calls Dog.bark(buddy) internally
# Output: Woof!
When you write buddy.bark(), Python translates that into Dog.bark(buddy). The buddy object is passed as self. You never type it yourself at the call site — Python handles it.
You can verify this by calling the method through the class directly instead of through an instance:
Dog.bark(buddy) # exactly the same as buddy.bark()
# Output: Woof!
Both calls produce the same result because they are literally the same operation. In both cases, Python passes buddy as the first argument — the dot-notation form on instances is simply a shorter way to write it. Understanding this equivalence is the key to understanding what self actually is: it is the instance Python passes in automatically.
Arrange the tokens below to build a correct method signature for a method named greet that takes self as its first parameter:
def, followed by the method name, then parentheses containing self as the first parameter, and finally a colon. class is used to define the class itself, not a method inside it.
self in __init__: Storing Instance Data
__init__ is the method Python calls automatically the moment a new instance is created. It runs immediately, before any other code in your program touches that object, which makes it the right place to set up the data the instance will carry. You use self inside __init__ to attach that data directly to the object.
class Dog:
def __init__(self, name, breed):
self.name = name # stored on this specific instance
self.breed = breed # stored on this specific instance
buddy = Dog("Buddy", "Labrador")
rex = Dog("Rex", "German Shepherd")
print(buddy.name) # Buddy
print(rex.name) # Rex
self.name = name stores the name argument directly on this instance as an instance attribute. buddy and rex each get their own separate .name and .breed — changing one never touches the other.
The attribute name on the left of the assignment does not have to match the parameter name on the right. self.name = name is common because the names match and that makes the code self-documenting — it is obvious what the attribute represents. You could write self.dog_name = name and it would work identically, but readers would have to think about why the names differ. Matching names is the convention because it eliminates that friction.
What self actually is at runtime
Inside __init__, self is the actual object in memory. You can confirm this with id():
class Dog:
def __init__(self, name):
print(id(self)) # memory address of the new object
self.name = name
buddy = Dog("Buddy")
print(id(buddy)) # same memory address as above
The two id() calls print the same number, confirming that self inside __init__ is the very same object you assigned to buddy once __init__ finished running. Nothing is copied or duplicated — it is one object the whole time.
Instance attribute vs. local variable
One of the most common early mistakes is writing a plain variable assignment instead of a self assignment. There is also a third form worth knowing about: a class-level variable, which is written directly inside the class body but outside any method. Unlike an instance attribute, a class-level variable is shared across all instances of the class — every object reads the same value unless you specifically override it on one. The table below compares all three forms. Click a row to see what differs.
- Stored where?
- On the object itself — accessible from anywhere via
instance.name - Survives after __init__?
- Yes. The attribute persists on the object for its entire lifetime.
- Stored where?
- Nowhere useful — it simply re-binds the local parameter name inside the method.
- Survives after __init__?
- No. The value disappears the moment __init__ returns. Nothing is stored on the object.
- Stored where?
- On the class itself — for example
species = "Canis lupus"written directly in the class body, not inside__init__. Every instance shares this value unless you override it on a specific instance withself.species = .... - Survives after __init__?
- Yes, because it belongs to the class and exists independently of any instance. Changing it on the class (
Dog.species = "wolf") updates it for all instances that have not overridden it. Changing it on one instance only affects that instance.
self in Other Methods: Accessing Your Data
Once __init__ has stored data on the instance, every other method in the class can reach that data through self. Any method that takes self as its first parameter can read an attribute with self.attribute, update it with self.attribute = new_value, or call another method on the same object with self.method_name().
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def deposit(self, amount):
self.balance += amount # modifies this instance's balance
print(f"Deposited {amount}. New balance: {self.balance}")
def summary(self):
print(f"{self.owner}: ${self.balance}")
account = BankAccount("Alice", 100)
account.deposit(50)
account.summary()
# Deposited 50. New balance: 150
# Alice: $150
When account.deposit(50) runs, Python passes account as self. That means self.balance inside deposit is the exact same value as account.balance outside the class — they are the same attribute on the same object. When deposit writes self.balance += amount, it is updating the object directly, and that change is visible everywhere that object is used.
Calling one method from another using self
Methods can call other methods on the same instance using self.method_name(). This lets you split logic into focused, reusable pieces rather than writing everything in one long method. Python passes the instance as self in those inner calls too, so the whole chain always operates on the same object:
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def is_overdrawn(self):
return self.balance < 0
def deposit(self, amount):
self.balance += amount
if self.is_overdrawn(): # calling another method via self
print("Warning: account is overdrawn.")
account = BankAccount("Alice", -10)
account.deposit(5)
# Warning: account is overdrawn.
Common self Mistakes
There are three mistakes beginners make with self repeatedly. Each one produces a specific error message, and once you know what to look for the fix is immediate.
Forgetting self in the method signature
If you define a method without self and then call it on an instance, Python raises a TypeError:
class Dog:
def bark(): # missing self
print("Woof!")
buddy = Dog()
buddy.bark()
# TypeError: Dog.bark() takes 0 positional arguments but 1 was given
The error message is telling you exactly what happened. Python tried to pass the buddy instance as the first argument — that is the "1" that was given. The method declared zero parameters, so it had nowhere to receive it. The fix is always the same: add self as the first parameter in the method definition.
When you see takes 0 positional arguments but 1 was given on a method call, the first thing to check is whether you forgot self in the method definition. Note that this error does not appear for static methods — those are intentionally defined without self because they do not operate on an instance.
Using self outside a class method
self is just a name — it has no special meaning outside a class. If you write it in a standalone function or at the module level, Python treats it as an ordinary variable. Outside a class, if you use self without having defined it first, you get a NameError:
def greet():
print(self.name) # NameError: name 'self' is not defined
greet()
There is no instance here, so there is no object for self to refer to. Python sees an undefined name and raises NameError. The fix is straightforward: if you need this function to operate on an object, make it a method inside a class and give it self as its first parameter.
Forgetting to use self when accessing an attribute
Inside a method, instance attributes live on self — they are not in scope as bare names. If you write the attribute name without self., Python searches for a local variable with that name, finds nothing, and raises a NameError:
class Counter:
def __init__(self):
self.count = 0
def increment(self):
count += 1 # NameError: name 'count' is not defined
# correct: self.count += 1
The commented correct version — self.count += 1 — tells Python exactly where to look: on the instance. That single prefix is the entire difference between an attribute update and a crash.
The class below should store a name on each instance and return it from get_name(). One line contains a bug. Click it, then hit check.
self.name = name. Writing name = name just re-assigns the local parameter to itself and discards it when __init__ returns. Nothing is stored on the instance, so get_name() raises an AttributeError.
How to Use self in a Python Class
Follow these four steps to correctly define and use self in any Python class. Each step builds on the previous one.
-
Define the class and write __init__ with self
Use the
classkeyword to declare your class. Inside, writedef __init__(self)as the first method. The moment Python creates a new instance, it calls__init__and passes the new object in asself. At this point the object exists but has no data on it yet — that is what the next step handles. -
Attach data to the instance using self
Inside
__init__, writeself.attribute_name = valuefor each piece of data the object should hold. For example,self.name = namestores the name on this specific instance. Each instance you create gets its own independent copy — changingbuddy.namenever affectsrex.name. -
Add instance methods that accept self
Define additional methods inside the class with
selfas the first parameter. Inside those methods,self.attribute_namereads the data you stored in step 2, and you can update it withself.attribute_name = new_value. Call other methods on the same instance withself.other_method()— Python passes the instance in automatically there too. -
Create an instance and call its methods
Instantiate the class by calling it like a function:
obj = MyClass(). Any arguments you pass go to__init__afterself. Then call methods using dot notation:obj.my_method(). You never supplyselfyourself — Python fills it in withobjautomatically at each call.
Python Learning Summary Points
selfis the first parameter of an instance method and holds a reference to the object the method was called on.- Python passes the calling instance as
selfautomatically — you never supply it yourself when calling a method. selfis a convention, not a keyword. Any valid name would work, but every Python project usesselfand you should too.- In
__init__, always writeself.attribute = valueto store data on the instance. Writingattribute = valuewithoutself.just creates a local variable that disappears when the method finishes. Writingattributewithoutself.inside any other method raises aNameError. - The same
selfflows through every method call on an object. When one method updatesself.balance, every other method that readsself.balancesees the updated value — they are all operating on the same object. - Forgetting
selfin a method signature produces aTypeError: takes 0 positional arguments but 1 was givenwhen you call the method on an instance. selfis different fromcls, which is used in class methods decorated with@classmethodand refers to the class rather than a specific instance. You will encounterclsonce you start writing more advanced class patterns — for now, every method you write will useself.
Frequently Asked Questions
self is the first parameter of an instance method in a Python class. When you call a method on an object — for example buddy.bark() — Python automatically passes that object as the first argument. The method receives it as self, which gives the method a reference to the specific object it is working with. Through self, the method can read the object's attributes, update them, and call other methods on the same object. Without self, a method would have no way of knowing which object's data to use.
When you call a method on an instance, Python automatically passes that instance as the very first argument to the method. The first parameter in the method definition is therefore where Python delivers it — which is why that position is always reserved for it. The name self is not enforced by Python; it is the universal convention that every Python developer and linter expects. Using any other name would work mechanically but would confuse everyone reading the code.
No — you can use any valid Python identifier. Python does not enforce the name. However, self is the universal convention followed by every Python project and checked by linters like pylint and ruff. Deviating from it will immediately stand out to any other developer reading your code, and most tools will warn you. There is no benefit to using a different name and real costs to doing so.
If you define a method without self and then call it on an instance, Python raises a TypeError saying the method takes 0 positional arguments but 1 was given. That one unexpected argument is the instance Python tried to pass automatically. A related improvement in Python 3.12: if you access an attribute without self. inside a method and the instance has an attribute with that exact name, Python now suggests self.<name> in the NameError message — making that related mistake easier to diagnose in recent versions.
self and cls are both conventional names for the first parameter of a method, but they serve different purposes. self is used in regular instance methods and refers to the object the method was called on. cls is used in class methods — those decorated with @classmethod — and refers to the class itself rather than any particular instance. A class method is typically used for things like alternative constructors. Static methods, marked with @staticmethod, receive neither: they are plain functions that happen to live inside the class namespace. For most beginner code, you will only encounter self.
No. self is not a reserved keyword in Python. Python's reserved keywords — words the language itself claims, like class, def, return, if, for, and while — cannot be used as variable or parameter names. self has no such restriction. It is simply the name the entire Python community has agreed to use for the first parameter of instance methods, and that agreement is so universal that breaking it is effectively never justified.
__init__ is the initializer method that Python calls automatically when you create a new instance of a class. self inside __init__ refers to the newly created object, and you use it to set the object's initial attributes with self.attribute = value. It is commonly called the constructor, though the more precise term is initializer — it sets the object up after Python has already created it.
No — self has no special meaning outside a class. Inside a class, Python uses it to deliver the current instance to a method. Outside a class, it is just an ordinary name. If you reference it without having assigned anything to it, Python raises a NameError, exactly as it would for any other undefined name. The Common Mistakes section of this tutorial includes a code example of this.