Module: Object Oriented Programming

Methods

Methods in Python Object-Oriented Programming (OOP)

Methods are functions defined inside a class. They operate on the data (attributes) of the class's instances (objects). They define the behavior of objects.

Key Concepts:

  • self: The first parameter of any method within a class is conventionally named self. It's a reference to the instance of the class on which the method is being called. Python automatically passes this reference when you call a method on an object. You use self to access and modify the object's attributes.
  • Instance Methods: These are the most common type of method. They require an instance of the class to be called.
  • Class Methods: These are bound to the class and not the instance. They receive the class itself (cls) as the first argument. They are often used for factory methods or to modify class-level attributes.
  • Static Methods: These are not bound to either the instance or the class. They don't receive self or cls as arguments. They are essentially regular functions that are logically grouped within the class.

1. Instance Methods

These methods operate on specific instances of a class.

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

    def bark(self):
        """Prints a barking message with the dog's name."""
        print(f"{self.name} says Woof!")

    def describe(self):
        """Prints a description of the dog."""
        print(f"This is {self.name}, a {self.breed}.")

# Create an instance of the Dog class
my_dog = Dog("Buddy", "Golden Retriever")

# Call the instance methods
my_dog.bark()      # Output: Buddy says Woof!
my_dog.describe()  # Output: This is Buddy, a Golden Retriever.

Explanation:

  • __init__(self, name, breed): This is the constructor (initializer) method. It's called when a new Dog object is created. It initializes the name and breed attributes of the object.
  • bark(self): This method makes the dog "bark". It accesses the name attribute using self.name.
  • describe(self): This method prints a description of the dog, using both self.name and self.breed.

2. Class Methods

Class methods are bound to the class and not the instance. They are defined using the @classmethod decorator. They receive the class itself (cls) as the first argument.

class Employee:
    num_of_employees = 0  # Class attribute

    def __init__(self, name, salary):
        self.name = name
        self.salary = salary
        Employee.num_of_employees += 1

    @classmethod
    def get_employee_count(cls):
        """Returns the total number of employees."""
        return cls.num_of_employees

    @classmethod
    def from_string(cls, emp_str):
        """Creates an Employee object from a string."""
        name, salary = emp_str.split('-')
        return cls(name, int(salary))  # Use cls to create a new instance

# Create instances
emp1 = Employee("Alice", 50000)
emp2 = Employee("Bob", 60000)

# Call the class method
print(Employee.get_employee_count())  # Output: 2

# Use the from_string class method
emp3 = Employee.from_string("Charlie-70000")
print(emp3.name, emp3.salary)  # Output: Charlie 70000
print(Employee.get_employee_count()) # Output: 3

Explanation:

  • @classmethod: This decorator indicates that the method is a class method.
  • get_employee_count(cls): This method accesses the class attribute num_of_employees using cls.num_of_employees. It doesn't need an instance of Employee to be called.
  • from_string(cls, emp_str): This is a factory method. It creates a new Employee object from a string representation. It uses cls to call the constructor (__init__) of the class. This is useful when you want to create objects in a different way than the standard constructor.

3. Static Methods

Static methods are not bound to either the instance or the class. They are defined using the @staticmethod decorator. They don't receive self or cls as arguments.

class MathUtils:
    @staticmethod
    def add(x, y):
        """Adds two numbers."""
        return x + y

    @staticmethod
    def is_positive(number):
        """Checks if a number is positive."""
        return number > 0

# Call the static methods
result = MathUtils.add(5, 3)
print(result)  # Output: 8

print(MathUtils.is_positive(10))  # Output: True
print(MathUtils.is_positive(-5))  # Output: False

Explanation:

  • @staticmethod: This decorator indicates that the method is a static method.
  • add(x, y): This method simply adds two numbers. It doesn't need access to the class or any instance data.
  • is_positive(number): This method checks if a number is positive. It's logically related to math operations, so it's grouped within the MathUtils class, but it doesn't depend on the class's state.

Summary Table:

Method Type Decorator First Argument Access to Instance Data Access to Class Data Use Cases
Instance Method None self Yes Yes Operating on object's attributes
Class Method @classmethod cls No Yes Factory methods, modifying class attributes
Static Method @staticmethod None No No Utility functions logically grouped with class

When to use which method type:

  • Instance Methods: Use when the method needs to access or modify the state of a specific object.
  • Class Methods: Use when the method needs to work with the class itself (e.g., creating instances in a specific way, modifying class-level attributes).
  • Static Methods: Use when the method is a utility function that's logically related to the class but doesn't need access to the class or instance data. They are essentially functions that are namespaced within the class.