Home / Topic Library / Python / Classes & OOP
🐍 Python Topic Library

Python Classes & OOP — Objects Explained Simply

A class is a blueprint; objects are the things built from it. OOP clicks the moment you build something real — so this whole guide builds one game character.

⚡ Quick Answer

Define with class Name:. The __init__ method runs when you create an object and sets its attributes via self. self is the object itself — Python passes it automatically to every method.

§Your first class

first_class.py
class Player:
    def __init__(self, name, hp=100):
        self.name = name       # attribute — this object's data
        self.hp = hp

    def take_damage(self, amount):
        self.hp -= amount
        if self.hp <= 0:
            return f"{self.name} is defeated!"
        return f"{self.name} has {self.hp} HP left"

hero = Player("Ada")           # __init__ runs here
print(hero.name)               # Ada
print(hero.take_damage(30))    # Ada has 70 HP left

§What is self, really?

self is just the object the method was called on. hero.take_damage(30) is secretly Player.take_damage(hero, 30) — Python fills in self for you.

self_demo.py
goblin = Player("Goblin", hp=40)
hero   = Player("Ada")

# same method, different self → different data:
print(goblin.take_damage(50))   # Goblin is defeated!
print(hero.hp)                  # 100 — untouched

§Class attributes vs instance attributes

attributes.py
class Player:
    game = "BitQuest"          # CLASS attribute — shared by all

    def __init__(self, name):
        self.name = name       # INSTANCE attribute — unique each

p1, p2 = Player("Ada"), Player("Alan")
print(p1.game, p2.game)        # BitQuest BitQuest
p1.name = "Ada the Great"      # only changes p1

§Inheritance — building on a class

inheritance.py
class Wizard(Player):                  # Wizard IS-A Player
    def __init__(self, name, mana=50):
        super().__init__(name, hp=80)   # run Player's setup too
        self.mana = mana

    def cast(self, spell):
        self.mana -= 10
        return f"{self.name} casts {spell}! ({self.mana} mana left)"

gandalf = Wizard("Gandalf")
print(gandalf.cast("fireball"))    # inherited + new powers
print(gandalf.take_damage(20))     # Player's method still works

§__str__ — printable objects

str_method.py
class Player:
    def __init__(self, name, hp=100):
        self.name, self.hp = name, hp

    def __str__(self):
        return f"Player({self.name}, {self.hp} HP)"

hero = Player("Ada")
print(hero)        # Player(Ada, 100 HP) — not <object at 0x...>

§Common Mistakes to Avoid

🚨 Watch out for these
  • Forgetting self in method definitionsdef take_damage(amount): inside a class raises TypeError on call — the first parameter must be self
  • Setting attributes on the class by accident — assigning inside __init__ without self (name = name) creates a useless local, not an attribute
  • Forgetting super().__init__() — a subclass that defines its own __init__ must call the parent's, or the parent's attributes never get created

§Frequently Asked Questions

What is self in Python?

self is the specific object a method is acting on. Python passes it automatically: hero.attack() becomes Player.attack(hero).

What does __init__ do?

__init__ is the initializer that runs automatically when you create an object — it's where you set up the object's starting attributes.

What's the difference between a class and an object?

A class is the blueprint (Player); objects are individual things built from it (hero, goblin), each with its own attribute values.

When should I actually use classes?

When you have data and behavior that belong together — a game character, a bank account, a quiz question. For simple scripts, plain functions are fine.

🎓 Want to master Python properly?This reference covers one topic — the full free course takes you from zero to projects, with quizzes and a certificate.
Start the Free Python Course →

§Related Python Topics

← FunctionsFile Handling →