⚙️ Object Methods

Object methods are functions that belong to objects and define what actions those objects can perform. While attributes store data about objects, methods provide the behaviors and functionality that make objects useful and interactive. Understanding methods transforms static data containers into dynamic, responsive entities.

Think of methods as the "verbs" of your objects - if a car object has attributes like color and speed, its methods might include start(), stop(), and accelerate(). Methods bridge the gap between data and action.

# Methods give objects behavior
class Calculator:
    def __init__(self):
        self.result = 0
    
    def add(self, number):
        self.result += number
        return self.result
    
    def multiply(self, number):
        self.result *= number
        return self.result
    
    def clear(self):
        self.result = 0
        return "Calculator cleared"

calc = Calculator()
print(calc.add(5))        # 5
print(calc.multiply(3))   # 15
print(calc.clear())       # Calculator cleared

🎯 Understanding Object Methods

Methods are functions defined inside classes that operate on object data. They have access to the object's attributes through the special self parameter, allowing them to read and modify the object's state.

Defining Methods

Methods are defined similar to regular functions but must include self as the first parameter. This parameter gives methods access to the object's attributes and other methods within the same class.

class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner
        self.balance = balance
    
    def get_balance(self):  # Method with no additional parameters
        return f"{self.owner}'s balance: ${self.balance}"
    
    def deposit(self, amount):  # Method with parameter
        if amount > 0:
            self.balance += amount
            return f"Deposited ${amount}. New balance: ${self.balance}"
        return "Invalid deposit amount"
    
    def transfer(self, other_account, amount):  # Method with multiple parameters
        if amount <= self.balance:
            self.balance -= amount
            other_account.balance += amount
            return f"Transferred ${amount} to {other_account.owner}"
        return "Insufficient funds"

# Using methods
alice_account = BankAccount("Alice", 100)
bob_account = BankAccount("Bob", 50)

print(alice_account.deposit(25))
print(alice_account.transfer(bob_account, 30))
print(bob_account.get_balance())

The Self Parameter

The self parameter is Python's way of giving methods access to the object they belong to. When you call a method, Python automatically passes the object as the first argument.

class Student:
    def __init__(self, name, grade):
        self.name = name
        self.grade = grade
        self.courses = []
    
    def add_course(self, course):
        # self refers to the specific student object
        self.courses.append(course)
        return f"{self.name} enrolled in {course}"
    
    def get_info(self):
        # self allows access to all object attributes
        course_list = ", ".join(self.courses) if self.courses else "None"
        return f"Student: {self.name}, Grade: {self.grade}, Courses: {course_list}"

# Each object gets its own 'self'
student1 = Student("Alice", "A")
student2 = Student("Bob", "B")

print(student1.add_course("Math"))     # self = student1
print(student2.add_course("Science"))  # self = student2
print(student1.get_info())             # self = student1

⚡ Method Parameters and Return Values

Methods can accept parameters just like regular functions, and they can return values to provide feedback or computed results. This flexibility allows methods to be interactive and responsive to different inputs.

Methods with Parameters

Parameters allow methods to receive external data and modify their behavior accordingly.

class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def resize(self, new_width, new_height):
        old_area = self.width * self.height
        self.width = new_width
        self.height = new_height
        new_area = self.width * self.height
        return f"Resized from {old_area} to {new_area} square units"
    
    def scale(self, factor):
        self.width *= factor
        self.height *= factor
        return f"Scaled by {factor}x. New size: {self.width}x{self.height}"
    
    def is_larger_than(self, other_rectangle):
        my_area = self.width * self.height
        other_area = other_rectangle.width * other_rectangle.height
        return my_area > other_area

rect1 = Rectangle(4, 3)
rect2 = Rectangle(5, 2)

print(rect1.resize(6, 4))
print(rect1.scale(2))
print(rect1.is_larger_than(rect2))

Methods with Return Values

Return values allow methods to provide feedback, computed results, or status information.

class ShoppingCart:
    def __init__(self):
        self.items = {}
    
    def add_item(self, item, price, quantity=1):
        if item in self.items:
            self.items[item]['quantity'] += quantity
        else:
            self.items[item] = {'price': price, 'quantity': quantity}
        return f"Added {quantity} {item}(s) to cart"
    
    def get_total(self):
        total = 0
        for item_data in self.items.values():
            total += item_data['price'] * item_data['quantity']
        return total
    
    def get_summary(self):
        if not self.items:
            return "Cart is empty"
        
        summary = []
        for item, data in self.items.items():
            line = f"{item}: ${data['price']} x {data['quantity']}"
            summary.append(line)
        
        return {
            'items': summary,
            'total': self.get_total(),
            'item_count': len(self.items)
        }

cart = ShoppingCart()
cart.add_item("Apple", 1.50, 3)
cart.add_item("Bread", 2.99)

print(f"Total: ${cart.get_total()}")
summary = cart.get_summary()
for item in summary['items']:
    print(item)

🚀 Special Methods (Magic Methods)

Python provides special methods that enable objects to work with built-in functions and operators. These methods have double underscores and unlock powerful functionality for your objects.

String Representation Methods

The __str__ and __repr__ methods control how objects appear when printed or converted to strings.

class Product:
    def __init__(self, name, price, stock):
        self.name = name
        self.price = price
        self.stock = stock
    
    def __str__(self):  # For end users
        return f"{self.name} - ${self.price}"
    
    def __repr__(self):  # For developers
        return f"Product('{self.name}', {self.price}, {self.stock})"
    
    def __len__(self):  # Enable len() function
        return self.stock

# Special methods in action
laptop = Product("Laptop", 999, 5)
print(laptop)          # Uses __str__
print(repr(laptop))    # Uses __repr__
print(len(laptop))     # Uses __len__
print(f"Stock: {len(laptop)} units")

Comparison and Arithmetic Methods

Special methods enable your objects to work with comparison operators and arithmetic operations.

class Score:
    def __init__(self, points):
        self.points = points
    
    def __str__(self):
        return f"{self.points} points"
    
    def __eq__(self, other):  # Enable == comparison
        return self.points == other.points
    
    def __lt__(self, other):  # Enable < comparison
        return self.points < other.points
    
    def __add__(self, other):  # Enable + operation
        return Score(self.points + other.points)
    
    def __sub__(self, other):  # Enable - operation
        return Score(self.points - other.points)

# Using comparison and arithmetic
score1 = Score(100)
score2 = Score(85)

print(f"Score 1: {score1}")
print(f"Score 2: {score2}")
print(f"Equal? {score1 == score2}")
print(f"Score 1 higher? {score1 > score2}")
print(f"Combined: {score1 + score2}")
print(f"Difference: {score1 - score2}")

Essential Method Patterns

Common method patterns solve recurring design problems and create consistent interfaces across different classes.

PatternPurposeExample
Factory MethodsCreate objects with specific configurationscreate_admin_user()
Validation MethodsCheck object state or input validityis_valid_email()
Conversion MethodsTransform object to different formatsto_json(), to_dict()
Utility MethodsProvide helper functionalitycalculate_age()
Event MethodsHandle state changes or notificationson_item_added()

🌟 Method Organization and Best Practices

Well-organized methods make classes easier to understand, test, and maintain. Following established patterns helps create professional, reusable code.

Method Categories

Organize methods into logical categories based on their purpose and responsibility.

class TaskManager:
    def __init__(self):
        self.tasks = []
        self.completed_count = 0
    
    # Creation/Modification methods
    def add_task(self, description, priority="medium"):
        task = {
            'id': len(self.tasks) + 1,
            'description': description,
            'priority': priority,
            'completed': False
        }
        self.tasks.append(task)
        return f"Added task {task['id']}: {description}"
    
    def complete_task(self, task_id):
        for task in self.tasks:
            if task['id'] == task_id and not task['completed']:
                task['completed'] = True
                self.completed_count += 1
                return f"Completed task {task_id}"
        return "Task not found or already completed"
    
    # Query methods
    def get_pending_tasks(self):
        return [task for task in self.tasks if not task['completed']]
    
    def get_completed_tasks(self):
        return [task for task in self.tasks if task['completed']]
    
    def get_task_count(self):
        return len(self.tasks)
    
    # Display methods
    def show_summary(self):
        pending = len(self.get_pending_tasks())
        return f"Tasks: {pending} pending, {self.completed_count} completed"

# Well-organized method usage
manager = TaskManager()
manager.add_task("Learn Python", "high")
manager.add_task("Buy groceries", "low")
manager.complete_task(1)

print(manager.show_summary())
print(f"Pending tasks: {len(manager.get_pending_tasks())}")

💡 Practical Applications

Building Interactive Objects

Methods enable objects to respond to user actions and maintain their state appropriately.

class GameCharacter:
    def __init__(self, name, health=100):
        self.name = name
        self.health = health
        self.max_health = health
        self.level = 1
        self.experience = 0
    
    def take_damage(self, damage):
        self.health = max(0, self.health - damage)
        if self.health == 0:
            return f"{self.name} has been defeated!"
        return f"{self.name} took {damage} damage. Health: {self.health}/{self.max_health}"
    
    def heal(self, amount):
        self.health = min(self.max_health, self.health + amount)
        return f"{self.name} healed {amount} HP. Health: {self.health}/{self.max_health}"
    
    def gain_experience(self, xp):
        self.experience += xp
        if self.experience >= self.level * 100:
            return self.level_up()
        return f"{self.name} gained {xp} XP"
    
    def level_up(self):
        self.level += 1
        self.max_health += 20
        self.health = self.max_health
        self.experience = 0
        return f"{self.name} leveled up! Now level {self.level}"
    
    def get_status(self):
        return f"{self.name} - Level {self.level} - HP: {self.health}/{self.max_health} - XP: {self.experience}"

# Interactive character
hero = GameCharacter("Hero")
print(hero.take_damage(30))
print(hero.heal(15))
print(hero.gain_experience(150))
print(hero.get_status())

Hands-on Exercise

Create a simple Calculator class with methods for basic math operations. Include methods for addition, subtraction, multiplication, division, and getting the last result. Store the result of operations in the calculator.

python
class Calculator:
    def __init__(self):
        # TODO: Initialize result attribute
        pass
    
    def add(self, number):
        # TODO: Add number to result
        pass
    
    def subtract(self, number):
        # TODO: Subtract number from result
        pass
    
    def multiply(self, number):
        # TODO: Multiply result by number
        pass
    
    def divide(self, number):
        # TODO: Divide result by number (handle division by zero)
        pass
    
    def get_result(self):
        # TODO: Return current result
        pass
    
    def clear(self):
        # TODO: Reset result to 0
        pass

# TODO: Test your calculator
calc = Calculator()
print(f"Initial result: {calc.get_result()}")
calc.add(10)
print(f"After adding 10: {calc.get_result()}")
calc.multiply(2)
print(f"After multiplying by 2: {calc.get_result()}")
calc.subtract(5)
print(f"After subtracting 5: {calc.get_result()}")

Solution and Explanation 💡

Click to see the complete solution
class Calculator:
    def __init__(self):
        # Initialize result attribute
        self.result = 0
    
    def add(self, number):
        # Add number to result
        self.result += number
        return self.result
    
    def subtract(self, number):
        # Subtract number from result
        self.result -= number
        return self.result
    
    def multiply(self, number):
        # Multiply result by number
        self.result *= number
        return self.result
    
    def divide(self, number):
        # Divide result by number (handle division by zero)
        if number != 0:
            self.result /= number
            return self.result
        else:
            print("Error: Cannot divide by zero")
            return self.result
    
    def get_result(self):
        # Return current result
        return self.result
    
    def clear(self):
        # Reset result to 0
        self.result = 0
        return self.result

# Test your calculator
calc = Calculator()
print(f"Initial result: {calc.get_result()}")
calc.add(10)
print(f"After adding 10: {calc.get_result()}")
calc.multiply(2)
print(f"After multiplying by 2: {calc.get_result()}")
calc.subtract(5)
print(f"After subtracting 5: {calc.get_result()}")

Key Learning Points:

  • 📌 Instance attributes: Use self.result to store calculator's current state
  • 📌 Method chaining: Return values allow methods to be used in sequence
  • 📌 State management: Object maintains its state between method calls
  • 📌 Error handling: Check for invalid operations like division by zero
  • 📌 Method organization: Group related functionality in logical methods

Learn more about class inheritance to discover how to build upon existing classes and create specialized versions.

Test Your Knowledge

Test what you've learned about object methods:

What's Next?

Now that you understand how to create powerful object methods, you're ready to learn about class inheritance. Inheritance allows you to build upon existing classes and create specialized versions without starting from scratch.

Ready to continue? Check out our lesson on Class Inheritance.

Was this helpful?

😔Poor
🙁Fair
😊Good
😄Great
🤩Excellent