Classes and Objects

Python 3.14 · ✓ verified by execution on 2026-07-25

Object-Oriented Programming (OOP) is a paradigm that allows you to group related data and functions into a single structure. In Python, this structure is called a Class, and when you use the class, you create an Instance (or object) of it.

Defining a Class and Instantiating Objects

A class definition creates a new namespace. You can think of it as a blueprint.

python
class EmptyRobot:
    pass

bot = EmptyRobot()
print(type(bot).__name__)
Output
EmptyRobot

To create an instance, you use function notation (EmptyRobot()). It returns a brand-new, independent object of that class type.

The __init__ Method

The most important method in any class is __init__. When Python creates a new instance, it automatically invokes __init__() on the newly created object so you can set its initial state.

python
class Robot:
    def __init__(self, name):
        self.name = name

bot = Robot('R2-D2')
print(bot.name)
Output
R2-D2

Note: __init__ is an initializer, not a constructor. It modifies the object after it has already been created. Because of this, it is an error to return anything other than None from __init__.

The self Parameter

You probably noticed the word self in the __init__ method above. When you call an instance method like bot.greet(), Python implicitly passes the object itself as the first argument.

python
class Robot:
    def __init__(self, name):
        self.name = name
    def greet(self):
        print('Hello, I am ' + self.name)

bot = Robot('C-3PO')
bot.greet()
Output
Hello, I am C-3PO

If you forget to include self as the first parameter in your method definitions, Python will complain that your method takes 0 arguments but 1 was given! (The 1 being passed is the instance). It is crucial to remember that the name self has absolutely no special meaning to Python; it is purely a very strong community convention.

Methods can also call other methods on the same object using self:

python
class Robot:
    def __init__(self):
        self.power = 100
    def drain(self):
        self.power -= 10
    def work(self):
        self.drain()
        print('Power:', self.power)

bot = Robot()
bot.work()
Output
Power: 90

Data Attributes

One of the unique features of Python compared to strictly typed languages is that data attributes spring into existence when they are first assigned to. You do not need to pre-declare them in the class body.

python
class Robot:
    pass

bot = Robot()
bot.power_level = 100  # Dynamically creating an attribute
print(bot.power_level)
Output
100

While dynamic creation is possible anywhere, it’s best practice to create all your instance attributes inside __init__ so that anyone reading your code knows exactly what data an object contains.

Each time you create a new instance, it gets its own independent copy of its attributes:

python
class Counter:
    def __init__(self):
        self.count = 0
    def increment(self):
        self.count += 1

a = Counter()
b = Counter()
a.increment()
print(a.count, b.count)
Output
1 0

Check yourself

What is the primary role of the __init__ method in a Python class?

Reveal answer

It initializes the state (attributes) of the newly created instance. — __init__ is an initializer that sets up the object's initial state. It does not return the object (that's __new__), and Python allows dynamically creating attributes later.

What does the 'self' parameter represent in an instance method?

Reveal answer

It is a strong convention for the first parameter, representing the instance calling the method. — 'self' has no special meaning to the Python language; it is merely a strong convention. The language always passes the calling instance as the first positional argument.

Where should you create instance variables so that each object has its own independent copy?

Reveal answer

Inside the __init__ method. — Variables declared directly in the class body become class variables, which are shared across all instances. Instance variables belong inside __init__.

Challenges

Challenge 1 +25 XP

Fix the bug! The Counter class is broken. The methods are missing the 'self' parameter, and __init__ is incorrectly returning a value. Fix the errors so the output is '2'.

python
  • Test 1 — expects "2\n"
Need a hint? (−25% XP)

Add 'self' as the first parameter to every method. Remove the string return from __init__.

Show solution (0 XP)
class Counter:
    def __init__(self):
        self.count = 0
        return None

    def click(self):
        self.count += 1

    def get_count(self):
        return self.count

# Do not change the code below
c = Counter()
c.click()
c.click()
print(c.get_count())

Challenge 2 +25 XP

Create a class named 'Dog'. It should have an __init__ method that takes a 'name' parameter and assigns it to self.name. It should also have a method 'bark' that prints 'Woof!'.

python
  • Test 1 — expects "Rex\nWoof!\n"
Need a hint? (−25% XP)

Define 'class Dog:'. Then define 'def __init__(self, name):' and 'def bark(self):'.

Show solution (0 XP)
class Dog:
    def __init__(self, name):
        self.name = name
    def bark(self):
        print('Woof!')

# Test your class
d = Dog('Rex')
print(d.name)
d.bark()