## Example: Here 'MyClass' defines some magic methods
# to add functionality behaviour to its instance
class MyClass:
def __init__(self, a, b, c, d):
self.some_id = a
self.some_name = b
self.some_age = c
self.some_values = d
# Define '__str__' to enable print functionality
def __str__(self):
"""Add doc string to describe their behaviour"""
return f"id: {self.some_id}, name: {self.some_name}"
# Define '__len__' to enable showing length of 'MyClass' using
# the 'len()' function
def __len__(self):
"""Returns length of some_values"""
return len(self.some_values)
# Define '__getitem__' for enabling iteration/indexing/slicing of items
def __getitem__(self, index):
"""Iterate through some_values"""
return self.some_values[index]
# Define '__call__' for making the instance callable
def __call__(self, new_value):
self.some_values.append(new_value)
print(f"{new_value} was added")
## Create a instance to check these functionalities
my_instance = MyClass(239034, "Bob", 23, [10, 45, 32, 67, 32, 65])
# Print functionality, '__str__()' is invoked automatically
# when 'print()' is called on 'my_instance'
print(my_instance) # id: 239034, name: Bob
# similarly length functionality, '__len__()' is invoked automatically
print(len(my_instance)) # 6
# Indexing and Slicing, '__getitem__()' is invoked
print(my_instance[0]) # 10
print(my_instance[0:3]) # [10, 45, 32]
# get all values using empty slice
print(my_instance[:]) # [10, 45, 32, 67, 32, 65]
# Iterating through the instance
for a in my_instance:
print(a) # 10 45 32 67 32 65
# Calling a instance,
my_instance(20) # 20 was added
my_instance(90) # 90 was added