Course Content
How to Add a Virtual Environment in Python
0/1
Set
0/1
Magic Methods
0/1
Python
About Lesson

Magic methods in Python are special methods that allow you to define how objects behave in certain situations. They are also known as “dunder methods” (short for “double underscore methods”) because their names are surrounded by double underscores (e.g., __init__, __str__, __add__).

Here’s an overview of some of the most commonly used magic methods in Python:

1. __init__(self, ...) – Constructor

  • Purpose: Initializes a new object of a class.
  • Usage: Used when you create an instance of a class to initialize the object’s state.

Example:

Python
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

2. __str__(self) – String Representation

  • Purpose: Defines the string representation of an object when str() or print() is called.
  • Usage: Return a string that gives a human-readable description of the object.

Example:

Python
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def __str__(self):
        return f"Person(name={self.name}, age={self.age})"

3. __repr__(self) – Official String Representation

  • Purpose: Defines the official string representation of an object, primarily used by the repr() function. It should return a string that can, in theory, be used to recreate the object.
  • Usage: Should ideally return a string that resembles valid Python code.

Example:

Python
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def __repr__(self):
        return f"Person('{self.name}', {self.age})"

4. __len__(self) – Length of Object

  • Purpose: Defines behavior for the len() function.
  • Usage: Return the length of an object. This is usually implemented for containers like lists or strings.

Example:

Python
class MyList:
    def __init__(self, items):
        self.items = items
    
    def __len__(self):
        return len(self.items)

5. __getitem__(self, key) – Indexing (Getter)

  • Purpose: Defines behavior for accessing items using indexing (e.g., obj[key]).
  • Usage: Return the item at the given key or index.

Example:

Python
class MyList: 
  def __init__(self, items): 
    self.items = items 
    
  def __getitem__(self, index): 
    return self.items[index]

6. __setitem__(self, key, value) – Item Assignment

  • Purpose: Defines behavior for setting items using indexing (e.g., obj[key] = value).
  • Usage: Assign a value to the item at the given key or index.

Example:

Python
class MyList:
    def __init__(self, items):
        self.items = items
    
    def __setitem__(self, index, value):
        self.items[index] = value

7. __delitem__(self, key) – Item Deletion

  • Purpose: Defines behavior for deleting items using indexing (e.g., del obj[key]).
  • Usage: Delete the item at the specified key or index.

Example:

Python
class MyList:
    def __init__(self, items):
        self.items = items
    
    def __delitem__(self, index):
        del self.items[index]

8. __iter__(self) – Iterator

  • Purpose: Makes an object iterable, enabling it to be used in a for loop or with functions like list().
  • Usage: Should return an iterator (typically, an object with a __next__ method).

Example:

Python
class MyList:
    def __init__(self, items):
        self.items = items
    
    def __iter__(self):
        for item in self.items:
            yield item

9. __next__(self) – Next Item in Iterator

  • Purpose: Returns the next item from the iterator.
  • Usage: Used when an object is part of an iterable.

Example:

Python
class MyIterator:
    def __init__(self, start, end):
        self.current = start
        self.end = end
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.current < self.end:
            self.current += 1
            return self.current - 1
        else:
            raise StopIteration

10. __call__(self, ...) – Callable Objects

  • Purpose: Allows an instance of the class to be called like a function.
  • Usage: Defines the behavior when an object is called as a function (e.g., obj()).

Example:

Python
class Adder:
    def __init__(self, value):
        self.value = value
    
    def __call__(self, num):
        return self.value + num

11. __eq__(self, other) – Equality Comparison

  • Purpose: Defines the behavior of the equality operator (==).
  • Usage: Used to compare two objects for equality.

Example:

Python
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def __eq__(self, other):
        return self.name == other.name and self.age == other.age

12. __ne__(self, other) – Inequality Comparison

  • Purpose: Defines the behavior of the inequality operator (!=).
  • Usage: Used to compare two objects for inequality.

Example:

Python
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def __ne__(self, other):
        return not (self == other)

13. __lt__(self, other) – Less Than Comparison

  • Purpose: Defines the behavior of the less than operator (<).
  • Usage: Used to compare two objects with the < operator.

Example:

Python
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def __lt__(self, other):
        return self.age < other.age

14. __add__(self, other) – Addition

  • Purpose: Defines the behavior of the addition operator (+).
  • Usage: Used to add two objects.

Example:

Python
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)

15. __enter__(self) and __exit__(self) – Context Management

  • Purpose: Used in context managers (i.e., the with statement) to manage setup and cleanup operations.
  • Usage: __enter__ defines the behavior for entering the context, and __exit__ defines the behavior for exiting.

Example:

Python
class FileOpener:
    def __init__(self, filename):
        self.filename = filename
    
    def __enter__(self):
        self.file = open(self.filename, 'r')
        return self.file
    
    def __exit__(self, exc_type, exc_value, traceback):
        if self.file:
            self.file.close()

16. __del__(self) – Destructor

  • Purpose: Defines the behavior when an object is about to be destroyed (garbage collected).
  • Usage: Cleanup operations before the object is destroyed.

Example:

Python
class Person:
    def __del__(self):
        print(f"{self.name} is being deleted.")

17. __contains__(self, item) – Containment Check

  • Purpose: Defines behavior for the in operator.
  • Usage: Used when checking if an item is contained within an object (e.g., item in obj).

Example:

Python
class MyList:
    def __init__(self, items):
        self.items = items
    
    def __contains__(self, item):
        return item in self.items