Learn What self Is in Python: Absolute Beginners Tutorial

Final Exam & Certification

Complete this tutorial and pass the 10-question final exam to earn a downloadable certificate of completion.

skip to exam

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.

Note

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:

python
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:

python
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.

code builder click a token to place it

Arrange the tokens below to build a correct method signature for a method named greet that takes self as its first parameter:

your code will appear here...
( self greet class : def )
Why: A method definition starts with 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.

python
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.

Pro Tip

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():

python
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 with self.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().

python
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:

python
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.
check your understanding question 1 of 4

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:

python
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.

Common Pitfall

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:

python
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:

python
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.

spot the bug click the line that contains the bug

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.

1 class Person:
2 def __init__(self, name):
3 name = name
4 def get_name(self):
5 return self.name
The fix: Line 3 should be 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.

  1. Define the class and write __init__ with self

    Use the class keyword to declare your class. Inside, write def __init__(self) as the first method. The moment Python creates a new instance, it calls __init__ and passes the new object in as self. At this point the object exists but has no data on it yet — that is what the next step handles.

  2. Attach data to the instance using self

    Inside __init__, write self.attribute_name = value for each piece of data the object should hold. For example, self.name = name stores the name on this specific instance. Each instance you create gets its own independent copy — changing buddy.name never affects rex.name.

  3. Add instance methods that accept self

    Define additional methods inside the class with self as the first parameter. Inside those methods, self.attribute_name reads the data you stored in step 2, and you can update it with self.attribute_name = new_value. Call other methods on the same instance with self.other_method() — Python passes the instance in automatically there too.

  4. 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__ after self. Then call methods using dot notation: obj.my_method(). You never supply self yourself — Python fills it in with obj automatically at each call.

Python Learning Summary Points

  • self is 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 self automatically — you never supply it yourself when calling a method.
  • self is a convention, not a keyword. Any valid name would work, but every Python project uses self and you should too.
  • In __init__, always write self.attribute = value to store data on the instance. Writing attribute = value without self. just creates a local variable that disappears when the method finishes. Writing attribute without self. inside any other method raises a NameError.
  • The same self flows through every method call on an object. When one method updates self.balance, every other method that reads self.balance sees the updated value — they are all operating on the same object.
  • Forgetting self in a method signature produces a TypeError: takes 0 positional arguments but 1 was given when you call the method on an instance.
  • self is different from cls, which is used in class methods decorated with @classmethod and refers to the class rather than a specific instance. You will encounter cls once you start writing more advanced class patterns — for now, every method you write will use self.

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.

Final Exam
Learn What self Is in Python
10 questions 80% to pass Certificate on completion

Enter your name as you would like it to appear on your certificate of completion, then start the exam. Questions are shuffled on every attempt.

Please enter your name before starting.
Question 1 of 10