Python Classes and Objects
Learn about classes and objects in Python, including their creation, methods, and attributes.
Last updated: 2024-12-24Today, we're going to dive into one of the most crucial topics in Python programming - Classes and Objects. These concepts form the backbone of Object-Oriented Programming (OOP) paradigm and play a vital role in creating complex programs.
What are Classes?
A class is a blueprint or a template that defines the attributes (properties) and behaviors (methods) of objects. It combines data and functions to create a new data type.
Let's start with a simple example:
class Car:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
def info(self):
return f"{self.year} {self.make} {self.model}"
Here:
Car
is the name of the class.__init__
is the constructor method, called when a new object is created.self
refers to the current instance of the class.info
is a class method.
What are Objects?
An object is a specific instance of a class. If a class is a blueprint, an object is a concrete thing created from that blueprint.
Let's create an object from our Car
class:
my_car = Car("Toyota", "Camry", 2022)
print(my_car.info()) # Output: 2022 Toyota Camry
Here, my_car
is an object of the Car
class.
Attributes and Methods
Attributes
Attributes are data that belong to a class or an object. They are of two types:
- Instance attributes: Specific to each object.
- Class attributes: Declared at the class level and shared by all objects.
class Car:
car_count = 0 # Class attribute
def __init__(self, make, model):
self.make = make # Instance attribute
self.model = model # Instance attribute
Car.car_count += 1
Methods
Methods are functions defined within a class. They are of three types:
- Instance methods: Regular methods with
self
parameter. - Class methods: Decorated with
@classmethod
, receivecls
parameter. - Static methods: Decorated with
@staticmethod
, receive neitherself
norcls
.
class Car:
car_count = 0
def __init__(self, make, model):
self.make = make
self.model = model
Car.car_count += 1
def info(self): # Instance method
return f"{self.make} {self.model}"
@classmethod
def total_cars(cls): # Class method
return f"Total number of cars: {cls.car_count}"
@staticmethod
def company_info(): # Static method
return "This is the Car class"
Inheritance
Inheritance is a mechanism of basing one class upon another class. It promotes code reusability and allows creating hierarchical relationships.
class ElectricCar(Car):
def __init__(self, make, model, battery_capacity):
super().__init__(make, model)
self.battery_capacity = battery_capacity
def info(self):
return f"{super().info()}, Battery capacity: {self.battery_capacity} kWh"
tesla = ElectricCar("Tesla", "Model 3", 75)
print(tesla.info()) # Output: Tesla Model 3, Battery capacity: 75 kWh
Here, the ElectricCar
class inherits from the Car
class and extends its functionality.
Encapsulation
Encapsulation is the bundling of data and the methods that operate on that data. In Python, this is typically done by convention, as Python doesn't fully support "private" attributes.
class BankAccount:
def __init__(self, owner, balance):
self.__owner = owner # Private attribute
self.__balance = balance # Private attribute
def display_balance(self):
return f"Balance: ${self.__balance}"
def deposit(self, amount):
if amount > 0:
self.__balance += amount
return f"${amount} deposited. {self.display_balance()}"
return "Invalid amount"
account = BankAccount("Alice", 1000)
print(account.display_balance()) # Output: Balance: $1000
print(account.deposit(500)) # Output: $500 deposited. Balance: $1500
# print(account.__balance) # This would raise an AttributeError
Polymorphism
Polymorphism is the ability to use methods with the same name from different classes. It enhances code flexibility.
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "Woof!"
class Cat(Animal):
def speak(self):
return "Meow!"
animals = [Dog(), Cat()]
for animal in animals:
print(animal.speak())
# Output:
# Woof!
# Meow!
Practical Exercise
Let's create a small project to reinforce our understanding. We'll model a library system:
class Book:
def __init__(self, title, author, ISBN, publication_year):
self.title = title
self.author = author
self.ISBN = ISBN
self.publication_year = publication_year
self.available = True
def info(self):
status = "Available" if self.available else "Checked out"
return f"'{self.title}' by {self.author}, {self.publication_year} ({status})"
class Library:
def __init__(self, name):
self.name = name
self.books = []
def add_book(self, book):
self.books.append(book)
return f"'{book.title}' has been added to the library"
def search_book(self, title):
for book in self.books:
if book.title.lower() == title.lower():
return book.info()
return "Book not found"
def check_out_book(self, title):
for book in self.books:
if book.title.lower() == title.lower() and book.available:
book.available = False
return f"'{book.title}' has been checked out"
return "Book is not available or already checked out"
# Create a library and add books
my_library = Library("My Library")
book1 = Book("To Kill a Mockingbird", "Harper Lee", "978-0446310789", 1960)
book2 = Book("1984", "George Orwell", "978-0451524935", 1949)
print(my_library.add_book(book1))
print(my_library.add_book(book2))
# Search for and check out a book
print(my_library.search_book("To Kill a Mockingbird"))
print(my_library.check_out_book("To Kill a Mockingbird"))
print(my_library.search_book("To Kill a Mockingbird"))
This project demonstrates the use of classes, objects, methods, and attributes, as well as the principles of encapsulation and polymorphism in practice.
Conclusion
Classes and Objects are fundamental concepts of OOP in Python. They provide powerful tools for organizing code, promoting reusability, and modeling complex systems. By understanding and applying these concepts well, you can create more efficient and flexible programs.