Object Oriented Programming Python Tutorial

Object Oriented Programming Python Tutorial
You are currently viewing Object Oriented Programming Python Tutorial
Object Oriented Programming Python Tutorial

Object Oriented Programming Python Tutorial

Object Oriented Programming Python Tutorial, Step by Step: learn OOP in Python. Videos, Notes, and Practical Examples are Included. Read Below Blog 🙂

Learn Python Basics with AI Tools

🔹 What is Object Oriented Programming (OOP)?

OOP (Object-Oriented Programming) is a way to write code by creating objects that represent real-world things.

🧠 Real-life example:

Imagine you’re designing a car. You don’t describe each car from scratch. You define a blueprint (class), and then you can make many cars (objects) using that blueprint.

💡 Simple definition:

“OOP helps organize code by grouping related data and actions into objects.”

✅ Why do we use Object Oriented Programming Python?

Because it helps us write code that is:

  • 1. Organized 📦
  • We group related data and actions into one place (a class), like packing everything about a “Car” in one box.
  • 2. Reusable 🔁
  • Once we create a class (blueprint), we can make many objects from it — no need to write the same code again and again.
  • 3. Easier to Maintain 🛠️
  • If something breaks or needs an update, we only change it in one place — inside the class — not everywhere in the code.
  • 4. Real-World Modeling 🌍
  • We can write code that looks like real-life things — like “Person”, “Dog”, “Account”, etc. — making it easier to understand.
  • 5. Safe 🔐
  • We can hide sensitive information inside a class (encapsulation), like hiding your bank balance from direct access.

🧠 Analogy:

Think of OOP like Lego blocks — once you build a block (class), you can reuse it, extend it, or protect parts of it — instead of rebuilding every time.

🧠 Core Types of Object Oriented Programming Python

Yes, OOP is built on two main things inside every class:

PartAlso CalledWhat it RepresentsExample
AttributesProperties / DataWhat the object hasname, age, balance
MethodsFunctions / BehaviorWhat the object doesdeposit(), greet()

✅ Real-Life Analogy: Dog

class Dog:
def __init__(self, name, breed): # Attributes
self.name = name
self.breed = breed

def bark(self): # Method
print(f"{self.name} says Woof!")
  • Attributes: name, breed → what the dog has
  • Method: bark() → what the dog does

🧱 Evergreen OOP Structure (Starter Formula)

Let me give you the evergreen, basic structure of OOP in Python — the one you can always follow when creating your own classes.

class ClassName:
    def __init__(self, attribute1, attribute2):
        self.attribute1 = attribute1
        self.attribute2 = attribute2

    def method1(self):
        # Do something using self.attribute1 or self.attribute2
        pass

    def method2(self):
        # Another action
        pass

# Creating object
obj = ClassName(value1, value2)

# Using method
obj.method1()

🧪 Example: Student Class

class Student:
def __init__(self, name, grade):
self.name = name
self.grade = grade

def show_info(self):
print(f"Name: {self.name}, Grade: {self.grade}")

# Create object
s1 = Student("Aman", "A")

# Use method
s1.show_info()

🧠 Always Remember This Pattern:

  • class → defines the blueprint
  • __init__() → constructor to set up data
  • self → refers to the current object
  • methods → define behavior/actions
  • object → actual item created from class

🔑 What is self in Python OOP?

🧠 Simple Definition:

self is like saying “me” inside the object — it lets the object refer to its own data and actions.


🚘 Car Example:

Imagine you have 2 cars: one red, one black.

Each car needs to know its own color.

class Car:
def __init__(self, color):
self.color = color # "self" means: this car's color

def show_color(self):
print(f"My color is {self.color}")
  • self.color means “this car’s color”
  • So, if car1 is red and car2 is black, each one knows its own color

👨‍💼 Friend Example:

class Friend:
def __init__(self, name):
self.name = name # "self" refers to this friend

def greet(self):
print(f"Hi! I am {self.name}")
  • When you create 2 friends (Anu, Vivek), self.name ensures each friend introduces themselves correctly.

📚 Book Example:

class Book:
def __init__(self, title):
self.title = title # "self" refers to the specific book

def read(self):
print(f"You're reading '{self.title}'")
  • If one book is “Harry Potter” and another is “Atomic Habits”, self.title keeps the correct identity for each book.

🔁 Analogy:

Think of self as the word “I” or “my” that each object uses to talk about itself.

A book says: “I am Atomic Habits”
A friend says: “I am Rahul”
A car says: “My color is red”

They say this using self.

🔹 Is self a default value?

Yes ✅ — self is the conventionally used name, but you can technically rename it to anything (like this, abc, etc.).

However, you should not change it — because:

  • self is the Python standard
  • Everyone understands it
  • It keeps your code readable and maintainable

🛑 So: Don’t change it, even though Python allows it.


❗ What happens if you don’t use self?

➤ 1. You can’t access attributes

If you skip self, Python won’t know you’re referring to the object’s own data.

class Car:
def __init__(color): # ❌ No self
color = color

def show_color():
print(color) # ❌ Will give NameError

Output:

NameError: name 'color' is not defined

Python thinks color is a local variable, not an attribute of the object.


➤ 2. You’ll get TypeError

If you try to define a method without self, calling it will throw an error:

class Car:
def start_engine(): # ❌ missing self
print("Engine started")

my_car = Car()
my_car.start_engine() # ❌ ERROR

Output:

TypeError: start_engine() takes 0 positional arguments but 1 was given

Because when you do my_car.start_engine(), Python automatically passes the object as the first argument — and it expects that to be self.


✅ Summary:

SituationResult
Don’t use self in attributesCan’t access object data
Don’t use self in methodsTypeError: takes 0 but 1 given
Rename self to something elseTechnically works but not recommended

🔍 What is __str__() In Object Oriented Programming Python?

🔹 Definition:

__str__() is a special method in Python used to define what should be printed when you do:

print(object_name)

🧠 Why use it?

Without __str__(), printing an object gives you this:

<__main__.Car object at 0x000001>

But with __str__(), you get a nice readable message instead.

💬 Analogy:

Imagine someone asks:

“Tell me about your friend.”

You wouldn’t say:

“Object located at 0xGHF003X”

Instead, you’d say:

“His name is Rahul, he’s 25 years old.”

That’s exactly what __str__() does — it returns a friendly summary of the object.


✅ Syntax:

def __str__(self):
return "Custom string here"

✅ Evergreen Template for __str__()

class ClassName:
    def __init__(self, attr1, attr2):
        self.attr1 = attr1
        self.attr2 = attr2

    def __str__(self):
        return f"Summary of {self.attr1}, {self.attr2}"

Use this in every class to make printed objects readable.

🆚 __str__() vs Custom Methods

Feature__str__()Custom Methods (start_engine(), greet(), etc.)
PurposeUsed to define how the object looks when printedUsed to define custom behaviors or actions
TriggersAutomatically called when using print(object)Manually called like object.method()
ReturnAlways returns a stringMay return something or just print something
Typical UseTo summarize object data in 1 lineTo perform actions like calculations, greetings, etc.
Built-in?Yes, special built-in methodNo, you define as per your need

✅ When to Use __str__()

Use it when:

  • You want to print the object and see a clean summary.
  • You want easy debugging.
  • You’re teaching or learning — makes object output readable.

🔁 Example: __str__() for Book

print(my_book)
# Output: Book: 'Atomic Habits' by James Clear

Without __str__(), this would just give a confusing memory address.


✅ When to Use Custom Methods

Use them when:

  • You want the object to do something, not just represent itself.
  • Examples:
    • Start a car
    • Greet a person
    • Calculate price
    • Update a record

🔁 Example: Custom Method for Car

tiago.start_engine()
# Output: The Black car's engine has started

This is an action, not a summary.


📌 Summary Table

TaskUseWhy
Show object info on print()__str__()Gives readable summary of object
Make the object “do” somethingCustom methodPerforms specific action/behavior

✅ Example Recap: Combined Structure

You can (and should) combine __str__() and custom methods in the same class. They work together perfectly but serve different purposes:

class Car:
def __init__(self, color, model, price):
self.color = color
self.model = model
self.price = price

def __str__(self):
return f"Car Model: {self.model}, Color: {self.color}, Price: ₹{self.price}" # Used when you do print(car)

def start_engine(self):
print(f"{self.model}'s engine has started.") # Custom behavior

def stop(self):
print(f"{self.model} has stopped.") # Another custom behavior

You can now do:

tiago = Car("Red", "XE", 560000)

print(tiago) # 🔁 Calls __str__()
tiago.start_engine() # ▶️ Calls your custom method
tiago.stop() # ▶️ Another custom method

💡 Use Cases:

ActionWhat Happens
print(tiago)Shows car summary using __str__()
tiago.start_engine()Starts engine using your method
tiago.stop()Stops the car

🔐 What is Encapsulation in Object Oriented Programming Python?

Encapsulation means:

Hide the data inside the class, and control how it’s seen (getter) and changed (setter).

And with getter-only, you allow people to see the value, but not change it.


🧠 Analogy:

Think of an ATM machine:

  • You see your balance (getter ✅)
  • You update your PIN or withdraw cash (setter ✅)
  • But you cannot touch the bank database directly (private data ❌)

✅ Why Use Getter Only?

  • Protects sensitive or read-only data
  • Prevents outside tampering
  • Gives control over how data is shown

🎯 Why Use Setter?

  • To update private data safely
  • To validate new values before accepting
  • To keep your program clean and secure

🌱 Evergreen Template for Getter Only

class ClassName:
    def __init__(self, data):
        self.__data = data  # 🔐 Private variable

    def get_data(self):
        return self.__data  # ✅ Only getter

🌱 Evergreen Template for Getter & Setter Both

class ClassName:
    def __init__(self, data):
        self.__data = data

    def get_data(self):
        return self.__data

    def set_data(self, new_data):
        if new_data is valid:
            self.__data = new_data
        else:
            print("❌ Invalid value")

🚘 Example: Car Class

class Car:
def __init__(self, model, price):
self.model = model
self.__price = price # 🔐 Private

def get_price(self):
return self.__price # ✅ Getter
car1 = Car("XE", 560000)

print(car1.model) # ✅ OK
print(car1.get_price()) # ✅ OK
print(car1.__price) # ❌ Error: cannot access private variable

🧩 Summary:

FeatureRole
__variablePrivate, cannot be touched
get_...()Safely shows the value

Kunal Lonhare

I am the founder of Kuku Courses