Skip to main content
Python for Beginners
CHAPTER 18 Beginner

Object-Oriented Programming (OOP)

Updated: May 17, 2026
30 min read

# Object-Oriented Programming (OOP)

Welcome to Chapter 18! OOP is one of the most important programming paradigms. It lets you model real-world entities as objects with properties and behaviors.

---

1. Learning Objectives

  • Understand OOP concepts (classes, objects, encapsulation).
  • Create classes with constructors and methods.
  • Use instance and class variables.
  • Implement special/magic methods.
  • Build a bank account system.

---

2. Classes and Objects

```python id="py18_ex1" class Dog: # Class variable (shared by all instances) species = "Canis familiaris" # Constructor (initializer) def __init__(self, name, breed, age): # Instance variables (unique to each object) self.name = name self.breed = breed self.age = age # Instance method def bark(self): return f"{self.name} says Woof! 🐕" def info(self): return f"{self.name} ({self.breed}), {self.age} years old"

# Creating objects (instances) dog1 = Dog("Buddy", "Labrador", 3) dog2 = Dog("Luna", "German Shepherd", 5)

print(dog1.bark()) # Buddy says Woof! 🐕 print(dog2.info()) # Luna (German Shepherd), 5 years old print(Dog.species) # Canis familiaris

1

Class vs Object: ┌──────────────────┐ │ Class: Dog │ ← Blueprint │ - name │ │ - breed │ │ - bark() │ └──────┬───────────┘ │ Creates ┌───┴───┐ ▼ ▼ ┌──────┐ ┌──────┐ │dog1 │ │dog2 │ ← Instances │Buddy │ │Luna │ └──────┘ └──────┘

123456
---

## 3. The self Parameter

`self` refers to the **current instance** of the class:

python id="py18_ex2" class Student: def __init__(self, name, grade): self.name = name # self.name = instance variable self.grade = grade def promote(self): self.grade += 1 # Modify instance variable print(f"{self.name} promoted to grade {self.grade}!")

s = Student("Alice", 10) s.promote() # Alice promoted to grade 11!

1234
---

## 4. Class Variables vs Instance Variables

python id="py18_ex3" class Employee: # Class variable company = "TechCorp" employee_count = 0 def __init__(self, name, salary): self.name = name # Instance variable self.salary = salary # Instance variable Employee.employee_count += 1

e1 = Employee("Alice", 80000) e2 = Employee("Bob", 75000)

print(Employee.company) # TechCorp print(Employee.employee_count) # 2 print(e1.name) # Alice

1234
---

## 5. Methods Types

python id="py18_ex4" class MyClass: count = 0 def __init__(self, value): self.value = value MyClass.count += 1 # Instance method — accesses instance data def show(self): return f"Value: {self.value}" # Class method — accesses class data @classmethod def get_count(cls): return f"Total instances: {cls.count}" # Static method — no access to instance or class @staticmethod def validate(value): return isinstance(value, (int, float))

obj1 = MyClass(10) obj2 = MyClass(20)

print(obj1.show()) # Value: 10 print(MyClass.get_count()) # Total instances: 2 print(MyClass.validate(42)) # True

1234
---

## 6. Magic/Dunder Methods

python id="py18_ex5" class Vector: def __init__(self, x, y): self.x = x self.y = y def __str__(self): return f"Vector({self.x}, {self.y})" def __repr__(self): return f"Vector(x={self.x}, y={self.y})" def __add__(self, other): return Vector(self.x + other.x, self.y + other.y) def __len__(self): return int((self.x2 + self.y2)**0.5) def __eq__(self, other): return self.x == other.x and self.y == other.y

v1 = Vector(3, 4) v2 = Vector(1, 2)

print(v1) # Vector(3, 4) print(v1 + v2) # Vector(4, 6) print(len(v1)) # 5 print(v1 == v2) # False

1234
---

## 7. Properties (Getters and Setters)

python id="py18_ex6" class Temperature: def __init__(self, celsius): self._celsius = celsius @property def celsius(self): return self._celsius @celsius.setter def celsius(self, value): if value < -273.15: raise ValueError("Below absolute zero!") self._celsius = value @property def fahrenheit(self): return (self._celsius * 9/5) + 32

temp = Temperature(100) print(temp.celsius) # 100 print(temp.fahrenheit) # 212.0 temp.celsius = 0 print(temp.fahrenheit) # 32.0

1234
---

## 8. Mini Project: Bank Account System

python id="py18_project" class BankAccount: bank_name = "PyBank" def __init__(self, owner, balance=0): self.owner = owner self._balance = balance self._transactions = [] @property def balance(self): return self._balance def deposit(self, amount): if amount <= 0: raise ValueError("Deposit must be positive!") self._balance += amount self._transactions.append(f"+${amount:.2f}") print(f" ✅ Deposited ${amount:.2f}") def withdraw(self, amount): if amount <= 0: raise ValueError("Withdrawal must be positive!") if amount > self._balance: print(f" ❌ Insufficient funds!") return self._balance -= amount self._transactions.append(f"-${amount:.2f}") print(f" ✅ Withdrew ${amount:.2f}") def statement(self): print(f"\n {'='*35}") print(f" {self.bank_name} - Account Statement") print(f" {'='*35}") print(f" Owner: {self.owner}") print(f" Balance: ${self._balance:.2f}") print(f" Transactions: {len(self._transactions)}") for t in self._transactions[-5:]: print(f" {t}") print(f" {'='*35}") def __str__(self): return f"BankAccount({self.owner}, ${self._balance:.2f})"

# Demo account = BankAccount("Alice", 1000) account.deposit(500) account.withdraw(200) account.withdraw(100) account.statement() ``

---

9. MCQs with Answers

Q1: __init__ is: A) Destructor B) Constructor C) Iterator D) Generator Answer: B

Q2: self refers to: A) The class B) Current instance C) Parent class D) Module Answer: B

Q3: Class variables are shared by: A) One instance B) All instances C) No instances D) Only methods Answer: B

Q4: @classmethod receives: A) self B) cls C) Nothing D) Both Answer: B

Q5: @staticmethod receives: A) self B) cls C) Nothing special D) Both Answer: C

Q6: __str__ is called by: A) repr() B) print() C) len() D) init() Answer: B

Q7: @property creates: A) Class variable B) Getter method C) Static method D) Private variable Answer: B

Q8: _variable convention means: A) Public B) Private (by convention) C) Protected D) Constant Answer: B

Q9: Dunder methods start and end with: A) _ B) __ C) # D) @ Answer: B — Double underscores.

Q10: Can a class have multiple constructors? A) Yes, directly B) No, use @classmethod alternatives C) Only in Python 2 D) Only with metaclasses Answer: B — Python uses @classmethod for alternative constructors.

---

10. Interview Questions

  1. 1. What is self? Reference to the current instance, passed automatically as the first argument to instance methods.
  1. 2. Class variable vs instance variable? Class variables are shared across all instances; instance variables are unique to each object.
  1. 3. What are magic/dunder methods? Special methods with double underscores that Python calls implicitly (e.g., __init__, __str__, __add__).
  1. 4. What is the @property decorator? Creates getter/setter methods that look like attributes, enabling validation and computed properties.
  1. 5. Can you have multiple __init__ methods? No. Use @classmethod for alternative constructors.

---

11. Summary

  • Classes are blueprints; objects are instances.
  • __init__ initializes objects; self refers to the current instance.
  • Class variables are shared; instance variables are unique.
  • @classmethod, @staticmethod, and @property provide different method types.
  • Magic methods (__str__, __add__`, etc.) customize object behavior.

---

12. Next Chapter Recommendation

In Chapter 19: Inheritance and Polymorphism, you'll learn to build class hierarchies and reuse code! 🚀

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·