Магічні методи (також відомі як дандер-методи) у Python — це спеціальні методи, які починаються і закінчуються двома символами підкреслення (__
). Вони дозволяють змінювати поведінку об'єктів і визначати, як об'єкт реагуватиме на стандартні операції, такі як додавання, віднімання, порівняння, виклик як функції тощо. Ось огляд кількох основних магічних методів і їх використання.
__init__
Метод __init__
використовується для ініціалізації об'єкта. Він викликається автоматично при створенні нового екземпляра класу і дозволяє встановлювати початкові значення атрибутів об'єкта.
class Human:
def __init__(self, name, age=0):
self.name = name
self.age = age
def say_hello(self):
return f'Hello! I am {self.name}'
bill = Human('Bill')
print(bill.say_hello()) # Hello! I am Bill
print(bill.age) # 0
jill = Human('Jill', 20)
print(jill.say_hello()) # Hello! I am Jill
print(jill.age) # 20
__str__
та __repr__
Метод __str__
відповідає за перетворення об'єкта в рядок, коли викликається функція str()
, або коли об'єкт друкується. Метод __repr__
використовується для повернення офіційного строкового представлення об'єкта, яке бажано було б бачити в середовищі розробки або коли об'єкт виводиться в інтерактивному режимі.
class Human:
def __init__(self, name, age=0):
self.name = name
self.age = age
def __str__(self):
return f'Hello! I am {self.name}'
bill = Human('Bill')
bill_str = str(bill)
print(bill_str) # Hello! I am Bill
__getitem__
та __setitem__
Методи __getitem__
та __setitem__
використовуються для доступу до елементів об'єкта за допомогою квадратних дужок, як у списках чи словниках.
class ListedValuesDict:
def __init__(self):
self.data = {}
def __setitem__(self, key, value):
if key in self.data:
self.data[key].append(value)
else:
self.data[key] = [value]
def __getitem__(self, key):
result = str(self.data[key][0])
for value in self.data[key][1:]:
result += ", " + str(value)
return result
l_dict = ListedValuesDict()
l_dict[1] = 'a'
l_dict[1] = 'b'
print(l_dict[1]) # a, b
__call__
Метод __call__
дозволяє зробити об'єкт класу викликаємим, як функцію. Це дає змогу викликати об'єкти з аргументами, ніби вони були функціями.
class Adder:
def __init__(self, add_value):
self.add_value = add_value
def __call__(self, value):
return self.add_value + value
two_adder = Adder(2)
print(two_adder(5)) # 7
print(two_adder(4)) # 6
three_adder = Adder(3)
print(three_adder(5)) # 8
print(three_adder(4)) # 7
__enter__
та __exit__
Менеджери контексту використовуються разом із конструкцією with ... as ...:
для управління ресурсами, такими як відкриті файли або з'єднання з базою даних. Метод __enter__
викликається на початку блоку with
, а метод __exit__
викликається при виході з блоку.
class Session:
def __init__(self, addr, port=8080):
self.connected = True
self.addr = addr
self.port = port
def __enter__(self):
print(f"connected to {self.addr}:{self.port}")
return self
def __exit__(self, exception_type, exception_value, traceback):
self.connected = False
if exception_type is not None:
print("Some error!")
else:
print("No problem")
localhost_session = Session("localhost")
with localhost_session as session:
print(session.connected) # True
print(localhost_session.connected) # False
__iter__
та __next__
Протокол ітерації у Python реалізується за допомогою методу __iter__
, який повертає ітератор, і методу __next__
, який повертає наступний елемент послідовності.
class Iterable:
MAX_VALUE = 10
def __init__(self):
self.current_value = 0
def __next__(self):
if self.current_value < self.MAX_VALUE:
self.current_value += 1
return self.current_value
raise StopIteration
class CustomIterator:
def __iter__(self):
return Iterable()
c = CustomIterator()
for i in c:
print(i)