Menu
Coddy logo textTech

Magic Methods Introduction

Part of the Object Oriented Programming section of Coddy's Python journey — lesson 33 of 64.

Magic methods (also called dunder methods) are special methods with double underscores at the beginning and end. Python calls them automatically in response to certain operations.

Here is an example of a class with magic methods:

class Book:
    def __init__(self, title, author, pages):
        self.title = title
        self.author = author
        self.pages = pages
    
    def __str__(self):
        return f"{self.title} by {self.author}"

The __init__ method is called automatically when you create an object:

my_book = Book("Python Programming", "John Smith", 350)

The __str__ method is called automatically when you convert the object to a string:

print(my_book)        # Calls __str__ automatically
print(str(my_book))   # Also calls __str__

Output:

Python Programming by John Smith
Python Programming by John Smith

Without __str__, printing would show the object's memory location:

class SimpleBook:
    def __init__(self, title):
        self.title = title

simple = SimpleBook("Test Book")
print(simple)  # <__main__.SimpleBook object at 0x...>

Add another magic method for length:

class Book:
    def __init__(self, title, author, pages):
        self.title = title
        self.author = author
        self.pages = pages
    
    def __str__(self):
        return f"{self.title} by {self.author}"
    
    def __len__(self):
        return self.pages

my_book = Book("Python Programming", "John Smith", 350)
print(len(my_book))   # Calls __len__ automatically

Output:

350

Key Point: Magic methods start and end with double underscores (__method__) and are called automatically by Python. They allow your objects to work with built-in functions like str(), len(), and operators, making your classes more Pythonic and intuitive to use.

challenge icon

Challenge

Easy

In this challenge, you'll implement a Counter class with magic methods.

  • counter.py - This is the file you need to edit, containing TODO comments to guide your implementation
  • driver.py - Contains extensive test cases

Implement the Counter class in counter.py and test cases in driver.py following the TODO comments. The class should support initialization with optional values, string representation, and addition operations.

Cheat sheet

Magic methods (dunder methods) are special methods with double underscores that Python calls automatically in response to certain operations.

Common magic methods:

  • __init__ - Called when creating an object
  • __str__ - Called when converting to string with str() or print()
  • __len__ - Called when using len() function
class Book:
    def __init__(self, title, author, pages):
        self.title = title
        self.author = author
        self.pages = pages
    
    def __str__(self):
        return f"{self.title} by {self.author}"
    
    def __len__(self):
        return self.pages

my_book = Book("Python Programming", "John Smith", 350)
print(my_book)        # Calls __str__ automatically
print(len(my_book))   # Calls __len__ automatically

Without __str__, printing shows the object's memory location instead of a readable format.

Try it yourself

# TODO: Import the Counter class from counter.py
# Use format: from counter import Counter

# Comprehensive test case handler
test_case = input()

if test_case == "init_test":
    # TODO: Test the initialization with default value
    # Create a counter with no arguments and print it
    # Expected output: "Count: 0"
    pass

elif test_case == "init_with_value":
    # TODO: Test initialization with a specific value
    # Create a counter with initial value 10 and print it
    # Note: print() implicitly calls __str__, but our focus here is testing __init__
    # Expected output: "Count: 10"
    pass


elif test_case == "addition":
    # TODO: Test the addition operation
    # Create a counter with value 3, add 7 to it, and print the result
    # Expected output: "Count: 10"
    pass

elif test_case == "chained_addition":
    # TODO: Test chained addition operations
    # Create a counter with value 1, add 2, then add 3 to the result, and print
    # Expected output: "Count: 6"
    pass

elif test_case == "negative_values":
    # TODO: Test with negative values
    # Create a counter with value -5 and print it
    # Then add -3 to it and print the result
    # Expected outputs: "Count: -5" and "Count: -8"
    pass

elif test_case == "zero_value":
    # TODO: Test with zero values
    # Create a counter with value 0, add 0, and print
    # Expected output: "Count: 0"
    pass

elif test_case == "large_values":
    # TODO: Test with large values
    # Create a counter with value 1000000 and add 9000000
    # Expected output: "Count: 10000000"
    pass

elif test_case == "multiple_counters":
    # TODO: Test interaction between multiple counters
    # Create counter1 with value 5 and counter2 with value 10
    # Print both counters
    # Expected outputs: "Count: 5" and "Count: 10"
    pass

elif test_case == "type_validation":
    # TODO: Test adding different types
    # Try adding a float (2.5) to a counter with value 5
    # Expected output: "Count: 7.5"
    pass
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming