17.1 Introduction to OOP
Object-oriented programming, usually called OOP, organizes a program around objects. An object combines related information and actions in one place. For example, a student object can store a name and grade and can also display that information. OOP helps divide large programs into smaller, understandable, reusable parts.
Example
class Student:
pass
student = Student()
print(type(student).__name__)
Output
Student
Output Explanation: The class Student is defined first. Student() creates one object from that class. Python checks the object type and displays Student.
17.2 Procedural vs Object-Oriented Programming
Procedural programming organizes instructions mainly with variables and functions. Object-oriented programming groups related data and behavior inside classes and objects. Both approaches can solve problems, but OOP is often easier to expand when a project contains many related items, such as customers, products, orders, vehicles, or students.
Example
def show_name(name):
print(name)
class Person:
def show_name(self, name):
print(name)
show_name("Sara")
Person().show_name("Omid")
Output
Sara
Omid
Output Explanation: The normal function prints Sara. The method inside Person prints Omid. Both approaches work, but the second keeps the behavior inside a class.
17.3 Classes
A class is a blueprint used to create objects. It describes the attributes and methods that its objects may use. A class does not represent one specific real item by itself. Instead, it gives Python a reusable design for creating many similar objects with the same general structure and behavior.
Example
class Car:
brand = "Toyota"
print(Car.brand)
Output
Toyota
Output Explanation: The Car class contains a class attribute named brand. Accessing Car.brand reads the value and prints Toyota.
17.4 Objects
An object is a real instance created from a class. If a class is a blueprint for a house, an object is one house built from that blueprint. Different objects from the same class can store different values. Objects help programs represent real items such as books, people, accounts, and products.
Example
class Book:
pass
book = Book()
book.title = "Python Basics"
print(book.title)
Output
Python Basics
Output Explanation: A Book object is created and stored in book. The title attribute is added to that object, and printing it displays Python Basics.
17.5 Creating Classes
You create a class with the class keyword, a class name, and a colon. The indented statements below it form the class body. Class names normally use capitalized words, such as BankAccount. A beginner class may contain pass, attributes, methods, or an initialization method depending on its purpose.
Example
class Animal:
species = "Dog"
print(Animal.species)
Output
Dog
Output Explanation: Python creates a class named Animal. Its species attribute contains Dog, so accessing the attribute prints Dog.
17.6 Creating Objects
After defining a class, create an object by writing the class name followed by parentheses. This process is called instantiation. Every object is a separate instance, even when several objects come from the same class. You can create as many objects as the program needs and store each one in a variable.
Example
class Customer:
pass
customer1 = Customer()
customer2 = Customer()
print(customer1 is customer2)
Output
False
Output Explanation: Two separate Customer objects are created. The is operator checks whether they are the exact same object. They are not, so the result is False.
17.7 Attributes
Attributes are values connected to a class or an object. They describe information such as a product name, student age, account balance, or car colour. You access an attribute by writing the object name, a dot, and the attribute name. Attributes allow objects to remember useful information.
Example
class Product:
pass
item = Product()
item.name = "Keyboard"
item.price = 30
print(item.name, item.price)
Output
Keyboard 30
Output Explanation: The item object receives name and price attributes. print() reads both values and displays them on one line.
17.8 Methods
A method is a function defined inside a class. It represents an action that objects can perform. For example, a dog can bark, a bank account can deposit money, and a student can display a grade. Instance methods normally receive self so they can work with the object that called them.
Example
class Dog:
def bark(self):
print("Woof!")
dog = Dog()
dog.bark()
Output
Woof!
Output Explanation: The dog object calls its bark method. The print statement inside the method runs and displays Woof!.
17.9 The `self` Parameter
The self parameter represents the current object inside an instance method. Python supplies it automatically when a method is called through an object. You use self to read or change that object’s attributes and call its other methods. The name self is a strong Python convention and should be used consistently.
Example
class Person:
def set_name(self, name):
self.name = name
def show_name(self):
print(self.name)
person = Person()
person.set_name("Lina")
person.show_name()
Output
Lina
Output Explanation: set_name stores Lina in the current object through self.name. show_name reads the same attribute and prints Lina.
17.10 The `__init__()` Method
The __init__() method initializes a new object. Python calls it automatically when an object is created. It commonly receives starting values and saves them as instance attributes. This ensures that each new object begins with the information it needs instead of requiring attributes to be added manually afterward.
Example
class Student:
def __init__(self, name, grade):
self.name = name
self.grade = grade
student = Student("Ali", 8)
print(student.name, student.grade)
Output
Ali 8
Output Explanation: Student("Ali", 8) calls __init__ automatically. The method stores the two values, and print() displays them.
17.11 Instance Attributes
Instance attributes belong to individual objects. They are usually created with self inside __init__() or another instance method. Two objects created from the same class can hold different instance values. This is useful for data that changes from one object to another, such as names, prices, scores, or balances.
Example
class Player:
def __init__(self, name, score):
self.name = name
self.score = score
player1 = Player("Mina", 10)
player2 = Player("Reza", 20)
print(player1.score)
print(player2.score)
Output
10
20
Output Explanation: Each Player object stores its own score. player1 has 10 and player2 has 20, so the outputs are different.
17.12 Class Attributes
A class attribute is defined directly inside a class and is shared by all objects unless an object replaces it with its own value. Class attributes are useful for information that should normally be common to every instance, such as a company name, school name, tax rate, or category.
Example
class Employee:
company = "North Star Ltd."
first = Employee()
second = Employee()
print(first.company)
print(second.company)
Output
North Star Ltd.
North Star Ltd.
Output Explanation: Both objects read the same company value from the Employee class, so the same text appears twice.
17.13 Instance Methods
An instance method works with one particular object and receives self as its first parameter. It can read and modify that object’s instance attributes. Most object behavior is written with instance methods, including changing an address, increasing a score, calculating a total, or displaying an account balance.
Example
class Counter:
def __init__(self):
self.value = 0
def increase(self):
self.value += 1
counter = Counter()
counter.increase()
counter.increase()
print(counter.value)
Output
2
Output Explanation: The counter starts at 0. Each call to increase adds 1, so after two calls the value is 2.
17.14 Class Methods
A class method works with the class instead of one particular object. It uses the @classmethod decorator and receives cls as its first parameter. Class methods are useful for changing shared class data or creating objects in alternative ways. They can be called through the class or an instance.
Example
class School:
name = "Central School"
@classmethod
def rename(cls, new_name):
cls.name = new_name
School.rename("Maple School")
print(School.name)
Output
Maple School
Output Explanation: rename receives the School class through cls and changes the shared name attribute. The updated class value is then printed.
17.15 Static Methods
A static method belongs logically to a class but does not need self or cls. It uses the @staticmethod decorator. Static methods are helpful for utility tasks connected to the class, such as validating data or performing a calculation, when the method does not need object attributes or shared class attributes.
Example
class Calculator:
@staticmethod
def add(a, b):
return a + b
print(Calculator.add(4, 6))
Output
10
Output Explanation: The static add method receives 4 and 6, returns their sum, and print() displays 10.
17.16 Modifying Attributes
Object attributes can usually be changed after an object is created. Assign a new value using the object name, a dot, and the attribute name. Methods can also update attributes through self. This allows objects to represent changing information such as a score, price, account balance, status, or address.
Example
class Account:
def __init__(self, balance):
self.balance = balance
account = Account(100)
account.balance = 150
print(account.balance)
Output
150
Output Explanation: The account begins with a balance of 100. A later assignment replaces it with 150, which is the value printed.
17.17 Deleting Attributes
You can remove an attribute from an object with the del statement. After deletion, trying to access that attribute causes an AttributeError unless the class provides another value with the same name. Attribute deletion should be used carefully because other parts of the program may still expect the information to exist.
Example
class User:
pass
user = User()
user.nickname = "Sky"
del user.nickname
print(hasattr(user, "nickname"))
Output
False
Output Explanation: The nickname attribute is created and then deleted. hasattr() checks whether it still exists and returns False.
17.18 Deleting Objects
The del statement can remove a variable that refers to an object. This does not always destroy the object immediately because another variable may still refer to it. Python manages memory automatically and removes objects when they are no longer reachable. Beginners should understand that del removes a reference name.
Example
class Note:
pass
note = Note()
other = note
del note
print(type(other).__name__)
Output
Note
Output Explanation: Deleting note removes only that variable. The variable other still refers to the same object, so its class name remains Note.
17.19 The `__dict__` Attribute
Many Python objects have a __dict__ attribute that stores their writable instance attributes in a dictionary. It can help beginners inspect what information an object currently contains. The keys are attribute names and the values are the stored data. It is useful for learning and debugging, although normal code usually accesses attributes directly.
Example
class Profile:
def __init__(self, name, age):
self.name = name
self.age = age
profile = Profile("Nora", 15)
print(profile.__dict__)
Output
{'name': 'Nora', 'age': 15}
Output Explanation: The object stores name and age as instance attributes. __dict__ shows both attributes and their values inside a dictionary.
17.20 Object Identity
Object identity tells whether two variables refer to the exact same object in memory. The is operator checks identity, while == usually checks whether values are equal. Two different objects can contain equal data but still have different identities. Understanding this difference prevents confusion when comparing mutable objects.
Example
first = [1, 2]
second = first
third = [1, 2]
print(first is second)
print(first is third)
print(first == third)
Output
True
False
True
Output Explanation: first and second refer to the same list, so is returns True. third is a different list, but its values are equal, so == returns True.
17.21 OOP Design Basics
Good OOP design gives each class one clear responsibility. A class should store data and behavior that naturally belong together. Use meaningful class, method, and attribute names. Avoid creating one enormous class that performs every task. Small focused classes are easier to understand, test, reuse, and change as a project grows.
Example
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
shape = Rectangle(4, 3)
print(shape.area())
Output
12
Output Explanation: The Rectangle class stores width and height and has one clear area method. Multiplying 4 by 3 produces 12.
17.22 Chapter Practice Exercises
Practice helps turn OOP ideas into real programming skills. In this section, create small classes and objects instead of only reading definitions. Work slowly and test every example. Try classes for a student, book, product, pet, and bank account. Add attributes, methods, initialization, and clear printed results.
Example
class Pet:
def __init__(self, name):
self.name = name
def introduce(self):
print("My pet is", self.name)
pet = Pet("Coco")
pet.introduce()
Output
My pet is Coco
Output Explanation: The exercise creates a Pet object with the name Coco. Calling introduce() prints a sentence containing the stored name. Try changing the name or adding an age attribute.
17.23 Chapter Mini Project
This mini project combines classes, objects, attributes, initialization, and methods. You will create a simple bank account that stores an owner and balance. Methods will deposit money, withdraw money when enough funds are available, and display the final balance. The project demonstrates how OOP groups related data and actions.
Example
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
if amount <= self.balance:
self.balance -= amount
def show_balance(self):
print(self.owner, "has $" + str(self.balance))
account = BankAccount("Maya", 100)
account.deposit(50)
account.withdraw(30)
account.show_balance()
Output
Maya has $120
Output Explanation: The account starts with 100. Depositing 50 raises it to 150, and withdrawing 30 reduces it to 120. The final method prints the owner and balance.