Python Instance Variables

In the last lesson you learned about Constructors. The constructor is where an object gets set up when it is born. But what is it setting up? It is setting the data that belongs to that one object. That data is what we call instance variables. That is what this lesson is about.

🤔 Why Instance Variables?

Say you are building an app with user profiles. Alex has a name, an age, and a city. Riya has her own name, age, and city. Both are users. So they share the same shape. But their actual values are different.

So here is the pain. Imagine every object built from the same class shared one set of values. Then setting Riya’s city would also change Alex’s city. That would be a mess. You want each object to carry its own data, kept apart from every other object.

That is exactly what instance variables give you.

  • An instance variable is a piece of data that belongs to one specific object.
  • Each object gets its own copy.
  • Change one object’s value and the others stay untouched.

📦 What Is an Instance Variable?

Think of a school class form. Two students sit in the same class. They both fill the same kind of form: name, roll number, city. Same blank fields, right? But each filled form holds that one student’s answers. Alex’s form says “Alex”. Riya’s form says “Riya”. Same template, different answers.

That is the whole idea. The blank template is the Python class. Each filled form is an object. The answers written on one form are its instance variables.

Here is the key idea in plain words:

  • An instance is one object made from a class.
  • An instance variable is a value stored on that one object.
  • You usually create instance variables inside __init__ using self.
  • self means “this particular object”, so self.name means “this object’s name”.

🛠️ The Syntax

You set an instance variable by assigning to self.something inside the constructor. Here is a small User class that stores a name and a city for each user.

class User:
def __init__(self, name, city):
self.name = name # instance variable
self.city = city # instance variable

Reading that line by line:

  • def __init__(self, name, city) runs on its own when you create a new user.
  • self is the object being built right now.
  • self.name = name takes the name value you passed in and stores it on this object.
  • self.city = city does the same for the city.

The plain values name and city are just temporary. The moment __init__ finishes, they are gone. But self.name and self.city stay attached to the object. So you can use them later.

🙋 What Is self, Really?

You keep seeing self everywhere. So let’s slow down and look at it properly. The thing to remember is simple: self is the particular object the method is working on right now.

When you write alex = User("Alex", "London"), Python makes a fresh object. Then it calls __init__ and quietly passes that fresh object in as self. So inside __init__, self is alex. Later when you call riya = User("Riya", "Toronto"), Python makes another object and passes that one in as self.

Here is why every method takes self first:

  • A method is shared by every object of the class. There is only one copy of the code.
  • But the code needs to know which object it is working on this time. Alex’s? Riya’s?
  • So Python hands the object in as the first argument. That argument is self.
  • Inside the method, self.balance means “this object’s balance”, not someone else’s.

So self is not magic. It is just a normal parameter that always points at the current object. You do not pass it yourself. Python fills it in for you when you call the method on an object.

class User:
def __init__(self, name):
self.name = name
def greet(self):
print("Hi, I am", self.name)
alex = User("Alex")
riya = User("Riya")
alex.greet() # self is alex here
riya.greet() # self is riya here

This calls the same greet method twice. But each call works on a different object.

Output

Hi, I am Alex
Hi, I am Riya

Same code, two different objects, two different results. That is self doing its job. It points at whichever object you called the method on.

👀 Two Objects, Two Sets of Values

Now the part that makes it click. Let’s build two users from the same class and give them different values. Then we print each one’s data.

class User:
def __init__(self, name, city):
self.name = name
self.city = city
alex = User("Alex", "London")
riya = User("Riya", "Toronto")
print(alex.name, "lives in", alex.city)
print(riya.name, "lives in", riya.city)

When you run this, each object prints its own values.

Output

Alex lives in London
Riya lives in Toronto

See what happened? Both alex and riya came from the same User class. But alex.city is "London" and riya.city is "Toronto". They do not share. Each object kept its own copy.

You read an instance variable with a dot: object.variable. So alex.name reads the name stored on alex. And riya.name reads the name stored on riya.

🔒 Proving They Are Independent

Let’s prove the objects really are separate. We will change one user’s city after creating it. Then we check whether the other user changed too.

class User:
def __init__(self, name, city):
self.name = name
self.city = city
alex = User("Alex", "London")
riya = User("Riya", "Toronto")
# change only Alex's city
alex.city = "Berlin"
print("Alex:", alex.city)
print("Riya:", riya.city)

Here is what it prints.

Output

Alex: Berlin
Riya: Toronto

We changed alex.city to "Berlin". Riya’s city did not move. It is still "Toronto". That is the whole point of instance variables. Each object holds its own data. So editing one object leaves the others alone. They really are independent.

Tip

A handy way to picture it: every object is its own little box. The instance variables are the things inside that box. Two boxes from the same class still have separate contents.

➕ Setting Instance Variables Outside __init__

Most of the time you set instance variables inside __init__. But that is a habit, not a hard rule. You can actually add a new instance variable from anywhere. Python is relaxed about this.

You can set one inside any method. Here a verify_email method adds an is_verified flag the first time it runs.

class User:
def __init__(self, name):
self.name = name
def verify_email(self):
self.is_verified = True # new instance variable, added here
alex = User("Alex")
alex.verify_email()
print(alex.name, "verified:", alex.is_verified)

Before you call verify_email, the object has no is_verified at all. After you call it, the object has one.

Output

Alex verified: True

You can even add an instance variable from outside the class, with a plain dot assignment. No method needed.

alex = User("Alex")
alex.country = "UK" # added from outside the class
print(alex.country)

Output

UK

So obj.x = ... just sticks a new variable onto that one object. It works. But here is the catch. If is_verified only gets created inside verify_email, then reading alex.is_verified before you call that method will crash. The variable is not there yet.

So the clean habit is this: set every instance variable inside __init__. Then every object starts life with all its variables already in place. No surprises later.

🆚 Instance Variables vs Class Variables

There is a second kind of variable you will meet soon: the class variable. The short contrast is worth knowing now.

  • An instance variable belongs to one object. Each object has its own copy.
  • A class variable belongs to the class itself. Every object shares the same one.

Here is a quick demo. species is shared by all dogs. name is unique to each dog.

class Dog:
species = "Canis familiaris" # class variable, shared by all dogs
def __init__(self, name):
self.name = name # instance variable, one per dog
a = Dog("Rex")
b = Dog("Bruno")
print(a.name, b.name) # different
print(a.species, b.species) # same shared value

Output

Rex Bruno
Canis familiaris Canis familiaris

See the split? The two dogs have different names. That is the instance variable doing its job. But they share one species, because that lives on the class, not on each object. We go deep on this in the next lesson, so for now just hold on to the one-line difference: instance is per object, class is shared. You can read the full story in Class Variables.

🧰 A More Real Example

Let’s make it feel like real code. Imagine a BankAccount class. Each account has an owner and a balance. Each account also tracks its own state. Money added to one should never show up in the other.

class BankAccount:
def __init__(self, owner, balance):
self.owner = owner
self.balance = balance
def deposit(self, amount):
self.balance += amount # read the current balance, add to it
alex_account = BankAccount("Alex", 100)
riya_account = BankAccount("Riya", 100)
alex_account.deposit(50)
print(f"{alex_account.owner} has {alex_account.balance}")
print(f"{riya_account.owner} has {riya_account.balance}")

Both accounts start with a balance of 100. Then Alex deposits 50. Watch what the balances are after that.

Output

Alex has 150
Riya has 100

Let’s read what happened, step by step:

  • self.balance += amount is just shorthand for “take this account’s balance, add the amount, store it back”.
  • It reads self.balance and updates self.balance. Both are this account’s balance.
  • Since alex_account and riya_account each have their own balance, only Alex’s went up.
  • Riya’s stayed at 100, because nothing touched her account.

This is why instance variables matter so much in real programs. Each object tracks its own state over time. Alex’s deposits change Alex’s balance only. They keep every object’s data safe and separate.

⚠️ Common Mistakes

A few slip-ups come up a lot when people first work with instance variables.

  • Forgetting self. Writing name = name inside __init__ does nothing useful. It just sets a temporary local value that disappears. You need self.name = name to store it on the object.
class User:
def __init__(self, name):
# ❌ Avoid: this does not save anything on the object
name = name
# ✅ Good: this attaches the value to this object
self.name = name
  • Leaving self out of a method definition. Every method that works on the object must list self as its first parameter. Forget it, and Python complains the moment you call the method.
class User:
# ❌ Avoid: no self, so the method cannot reach the object's data
def greet():
print("Hi")
# ✅ Good: self is the first parameter
def greet(self):
print("Hi,", self.name)
  • Reading a variable that was never set. If you never assigned self.email anywhere, then alex.email will raise an error.

Output

AttributeError: 'User' object has no attribute 'email'
  • Expecting objects to share values. They do not. Two objects from the same class have totally separate instance variables. If you change one, the other does not change. That is by design.

  • Mixing up class and instance variables. Data that should be unique per object (like a name or a balance) belongs on self inside __init__. Only put a value on the class itself when every object truly shares it.

✅ Best Practices

Small habits that keep your classes clean.

  • Set every instance variable inside __init__ so each object starts in a known, complete state.
  • Use clear names that say what the value is: self.balance, not self.b.
  • Read and write through self inside methods, like self.balance, so the method always works on the right object.
  • Keep one piece of real-world data in each instance variable. One User stores one name, one city, one email.
  • Use a class variable only for things truly shared by all objects. Keep per-object data on self.

🧩 What You’ve Learned

A quick recap of the main ideas.

  • ✅ An instance variable is data that belongs to one specific object.
  • ✅ You usually create instance variables inside __init__ with self.name = value.
  • self means “this particular object”, so self.city is that object’s own city, and that is why every method takes self first.
  • ✅ Each object gets its own copy, so changing one object never touches another.
  • ✅ You read an instance variable with a dot: object.variable.
  • ✅ Instance variables are per object; class variables are shared by all objects.

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    Where are instance variables usually created?

    Why: Instance variables are normally set inside __init__ by assigning to self, like self.name = name.

  2. 2

    If alex.city is changed to "Berlin", what happens to riya.city?

    Why: Each object has its own copy of its instance variables, so changing one object does not affect another.

  3. 3

    What does self mean inside a method?

    Why: self refers to the specific object being used, so self.balance means that object's own balance.

  4. 4

    How is an instance variable different from a class variable?

    Why: An instance variable belongs to one object (each gets its own copy), while a class variable lives on the class and is shared by every object.

🚀 What’s Next?

You now know how each object keeps its own data with instance variables. Next, let’s look at data that is shared across every object of a class.

Class Variables

Share & Connect