When I build a small reporting script, I often begin with a few functions and dictionaries. That works well until the script needs to manage report settings, file locations, validation rules, and export history. At that point, passing many related values between functions becomes difficult.
This is where object-oriented programming (OOP) helps. You can group related data and behavior in one reusable unit instead of spreading it across your script.
Python is an object-oriented language, but it also supports procedural and functional programming. Let’s look at what that means, how Python classes work, and when OOP makes sense in real projects.
Is Python an Object-Oriented Language?
Yes, Python is an object-oriented language. In fact, almost everything you use in Python is an object.
A string, number, list, dictionary, function, and class instance all behave as objects. An object stores data and provides actions you can perform on that data.
For example, this string has a built-in method called upper():
report_name = "monthly sales report"
print(report_name.upper())
Output:
MONTHLY SALES REPORT
Here, report_name is a string object. The upper() method belongs to the string object and returns an uppercase version of its value.
The same idea applies to lists:
report_files = ["january.xlsx", "february.xlsx"]
report_files.append("march.xlsx")
print(report_files)
Output:
['january.xlsx', 'february.xlsx', 'march.xlsx']
You can see the output in the screenshot below.

The append() method belongs to the list object. Python gives built-in data types their own behavior through methods, which is a clear sign of object-oriented design.
If you are still getting comfortable with values and names in Python, start with this guide on Python variables. Understanding variables makes classes much easier to follow.
Why Python Is an Object-Oriented Language
Python supports the main ideas behind object-oriented programming:
- Classes, which act as blueprints for objects
- Objects, which are working instances created from classes
- Encapsulation, which keeps related data and code together
- Inheritance, which lets one class reuse another class’s features
- Polymorphism, which lets different objects use the same method name in different ways
You do not need to use every OOP feature in every Python script. However, Python gives you the tools when your application starts growing.
For example, a quick script that reads one CSV file may only need functions. A report automation tool that handles multiple report types, output formats, and schedules often becomes easier to manage with classes.
Classes and Objects in Python
A class is a blueprint. An object is a specific item created from that blueprint.
Think about a report generator. Every report may have a name, source file, and output format. Instead of storing these values separately, create a class that keeps them together.
class Report:
def __init__(self, name, source_file, output_format):
self.name = name
self.source_file = source_file
self.output_format = output_format
def show_details(self):
print(f"Report: {self.name}")
print(f"Source: {self.source_file}")
print(f"Format: {self.output_format}")
This code defines a class named Report.
The __init__() method is a constructor. Python runs it automatically when you create a new object. It sets the starting values for that object.
The self parameter refers to the current object. For example, self.name stores the name inside the specific report object you create.
Now create an object from the class:
sales_report = Report(
"Monthly Sales",
"sales_data.csv",
"xlsx"
)
sales_report.show_details()
Output:
Report: Monthly Sales
Source: sales_data.csv
Format: xlsx
You can see the output in the screenshot below.

The sales_report object has its own data and can run the show_details() method. For a deeper look at this setup, see how to use class constructors with parameters in Python.
Pro Tip: I have found that a class becomes useful when several functions keep accepting the same group of values. Instead of passing
file_name,folder_path,report_date, andformateverywhere, I group them inside one object.
Python Classes Hold Data and Behavior
The main benefit of a class is that it keeps related attributes and methods together.
An attribute stores data. A method is a function defined inside a class. In a reporting tool, the report name is an attribute, while exporting the report is a method.
Here is a more practical version of the Report class:
class Report:
def __init__(self, name, rows):
self.name = name
self.rows = rows
self.is_exported = False
def row_count(self):
return len(self.rows)
def export(self):
if not self.rows:
print("Cannot export an empty report.")
return
self.is_exported = True
print(f"{self.name} exported with {self.row_count()} rows.")
Create and use the object:
sales_rows = [
{"region": "North", "sales": 12500},
{"region": "South", "sales": 9800},
]
sales_report = Report("Monthly Sales", sales_rows)
sales_report.export()
print(sales_report.is_exported)
Output:
Monthly Sales exported with 2 rows.
True
You can see the output in the screenshot below.

The object now owns both the report data and the rules for exporting it. This design reduces the chance that another part of your code changes is_exported at the wrong time.
It also helps to know the difference between functions and methods in Python. A function can stand alone, while a method belongs to a class or object.
Inheritance in Python OOP
Inheritance lets one class build on another class. You use it when several objects share common data or behavior.
For example, a reporting automation script may generate CSV and Excel reports. Both report types need a name and rows, but each one exports differently.
class Report:
def __init__(self, name, rows):
self.name = name
self.rows = rows
def summary(self):
return f"{self.name}: {len(self.rows)} rows"
class CSVReport(Report):
def export(self):
print(f"Exporting {self.name} as CSV.")
class ExcelReport(Report):
def export(self):
print(f"Exporting {self.name} as Excel.")
The CSVReport and ExcelReport classes inherit from Report. They reuse the constructor and summary() method without copying that code.
csv_report = CSVReport("Website Traffic", [120, 145, 160])
excel_report = ExcelReport("Sales Summary", [4500, 5200])
print(csv_report.summary())
csv_report.export()
print(excel_report.summary())
excel_report.export()Output:
Website Traffic: 3 rows
Exporting Website Traffic as CSV.
Sales Summary: 2 rows
Exporting Sales Summary as Excel.
This approach makes your code easier to extend. Later, you can add PDFReport without rewriting the common report logic.
When a child class needs to run its parent class constructor, use super(). You can learn more in this guide on how to call a super constructor in Python.
Polymorphism Makes Code Flexible
Polymorphism means different objects can respond to the same method name in their own way.
In the previous example, both report objects use export(). However, CSVReport and ExcelReport run different export actions.
reports = [
CSVReport("Traffic Data", [100, 120]),
ExcelReport("Revenue Data", [7800, 9100]),
]
for report in reports:
report.export()
Output:
Exporting Traffic Data as CSV.
Exporting Revenue Data as Excel.
The loop does not need to check the report type. It simply calls export(). Each object handles the job correctly.
This becomes valuable in larger automation scripts. For example, you might loop through different data sources, notification methods, or file exporters without building long if and elif blocks.
Is Everything in Python an Object?
In practical terms, yes. Python treats built-in values as objects, including integers, strings, lists, tuples, dictionaries, and functions.
You can check an object’s type with the type() function:
report_name = "Sales Report"
report_count = 12
report_rows = ["North", "South", "West"]
print(type(report_name))
print(type(report_count))
print(type(report_rows))
Output:
<class 'str'>
<class 'int'>
<class 'list'>
You can also use isinstance() when you need to verify whether a value belongs to a class:
sales_report = Report("Monthly Sales", [])
print(isinstance(sales_report, Report))
print(isinstance(sales_report, object))Output:
True
True
Every custom class ultimately connects to Python’s base object class. This built-in structure gives Python a consistent object system while keeping the syntax simple.
When Should You Use OOP in Python?
Use OOP when your code manages entities that have both data and behavior. In my projects, classes work especially well for automation jobs, API clients, data processing pipelines, GUI applications, and reusable business rules.
For example, use a class when you need to represent:
- A report with data, export settings, and validation rules
- A customer with contact details and account actions
- A file processor with input paths, filters, and output logic
- An API client with authentication, request methods, and error handling
- A desktop application with windows, buttons, and user state
Do not create a class only because Python supports OOP. A small script with one task may remain cleaner with a few well-named functions.
Things to Keep in Mind
- Avoid unnecessary classes: Use a class when it groups related data and behavior; do not turn every small function into a class.
- Keep each class focused: A
Reportclass should manage reports, not also send emails, read databases, and process user login. - Use clear names: Name classes with singular nouns such as
Report,Customer, orFileProcessor; follow consistent Python naming conventions. - Protect object state: Keep important updates inside methods, such as
export()ormark_complete(), instead of changing attributes randomly across your code. - Prefer composition when needed: If one object uses another object, composition often creates a cleaner design than deep inheritance chains.
- Handle errors near the action: Catch expected file, input, or export errors inside the method that performs that work.
Frequently Asked Questions
Is Python fully object-oriented?
Python strongly supports object-oriented programming, but it is not limited to OOP. You can write procedural scripts with functions, functional-style code, or class-based applications. This flexibility is one reason Python works well for both small scripts and larger applications.
Is everything in Python an object?
Almost every value you work with in Python is an object, including strings, integers, lists, dictionaries, and functions. Each object has a type, attributes, and often built-in methods. Python classes also create objects.
Do I need OOP to learn Python?
No, you should first understand variables, conditions, loops, functions, lists, and dictionaries. Learn OOP after you can build small scripts comfortably. Classes make more sense when you see a real need to group data and behavior.
What is the difference between a class and an object in Python?
A class is a blueprint that describes what an object should contain and do. An object is an actual instance created from that class. For example, Report is a class, while sales_report is an object.
Is Python better with OOP or functions?
Neither approach wins in every situation. Functions work well for small, direct tasks, while OOP works well when your program handles connected data and repeated behavior. Many useful Python applications combine both approaches.
Can Python classes inherit from more than one class?
Yes, Python supports multiple inheritance, which means one class can inherit from more than one parent class. Use it carefully because it can make code harder to understand and debug. Start with single inheritance or composition unless you have a clear reason to add more complexity.
Python is an object-oriented language because it supports classes, objects, encapsulation, inheritance, and polymorphism. Start with simple classes for real entities in your scripts, then add advanced OOP patterns only when your project needs them.
You May Also Like
- Python dataclass guide
- Build a simple OOP project in Python
- Python composition vs inheritance
- Python abstract base classes
- Python method resolution order explained

Bijay Kumar is an experienced Python and AI professional who enjoys helping developers learn modern technologies through practical tutorials and examples. His expertise includes Python development, Machine Learning, Artificial Intelligence, automation, and data analysis using libraries like Pandas, NumPy, TensorFlow, Matplotlib, SciPy, and Scikit-Learn. At PythonGuides.com, he shares in-depth guides designed for both beginners and experienced developers. More about us.