About Lesson
Magic Methods in Python
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()
orprint()
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 likelist()
. - 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