Что такое служебный метод dict?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Служебные методы dict в Python
Служебные методы dict (dunder methods или magic methods) — это специальные методы, которые начинаются и заканчиваются двойными подчеркиваниями (__). Они позволяют объектам работать с операторами Python и стандартными функциями, как если бы они были встроенными типами.
Основные dunder методы dict
init и new
class MyDict:
def __init__(self, **kwargs):
self.data = kwargs
def __new__(cls, *args, **kwargs):
# Вызывается перед __init__
instance = super().__new__(cls)
return instance
d = MyDict(name="Alice", age=30)
print(d.data) # {name: Alice, age: 30}
getitem и setitem
Позволяют использовать индексацию dict[key]:
class CustomDict:
def __init__(self):
self.storage = {}
def __getitem__(self, key):
# d[key]
print(f"Получаю значение для {key}")
return self.storage.get(key)
def __setitem__(self, key, value):
# d[key] = value
print(f"Устанавливаю {key}={value}")
self.storage[key] = value
d = CustomDict()
d["name"] = "Alice" # Вызовет __setitem__
value = d["name"] # Вызовет __getitem__
delitem
Позволяет удалять элементы через del dict[key]:
class CustomDict:
def __init__(self):
self.storage = {}
def __delitem__(self, key):
# del d[key]
print(f"Удаляю {key}")
del self.storage[key]
d = CustomDict()
d.storage["name"] = "Alice"
del d["name"] # Вызовет __delitem__
len
Позволяет использовать len(dict):
class CustomDict:
def __init__(self):
self.storage = {}
def __len__(self):
return len(self.storage)
def __setitem__(self, key, value):
self.storage[key] = value
d = CustomDict()
d["a"] = 1
d["b"] = 2
print(len(d)) # 2
contains
Позволяет использовать in оператор:
class CustomDict:
def __init__(self):
self.storage = {}
def __contains__(self, key):
return key in self.storage
def __setitem__(self, key, value):
self.storage[key] = value
d = CustomDict()
d["name"] = "Alice"
print("name" in d) # True
print("age" in d) # False
iter и next
Позволяют итерировать по объекту:
class CustomDict:
def __init__(self, **kwargs):
self.data = kwargs
self.keys_list = list(kwargs.keys())
self.index = 0
def __iter__(self):
return iter(self.data)
def __next__(self):
if self.index >= len(self.keys_list):
raise StopIteration
key = self.keys_list[self.index]
self.index += 1
return key
d = CustomDict(name="Alice", age=30)
for key in d:
print(key) # name, age
Арифметические операции
add, sub, mul
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __sub__(self, other):
return Vector(self.x - other.x, self.y - other.y)
def __mul__(self, scalar):
return Vector(self.x * scalar, self.y * scalar)
def __repr__(self):
return f"Vector({self.x}, {self.y})"
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2) # Vector(4, 6)
print(v1 - v2) # Vector(-2, -2)
print(v1 * 2) # Vector(2, 4)
Операторы сравнения
eq, lt, gt
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __eq__(self, other):
return self.age == other.age
def __lt__(self, other):
return self.age < other.age
def __gt__(self, other):
return self.age > other.age
def __repr__(self):
return f"Person({self.name}, {self.age})"
p1 = Person("Alice", 30)
p2 = Person("Bob", 25)
print(p1 == p2) # False
print(p1 > p2) # True
print(p2 < p1) # True
people = [p1, p2]
people.sort() # Использует __lt__
print(people) # [Person(Bob, 25), Person(Alice, 30)]
str и repr
class Product:
def __init__(self, name, price):
self.name = name
self.price = price
def __str__(self):
# Для пользователя (print)
return f"{self.name} стоит {self.price} руб."
def __repr__(self):
# Для разработчика (интерпретатор)
return f"Product({self.name}, {self.price})"
p = Product("Книга", 500)
print(str(p)) # Книга стоит 500 руб.
print(repr(p)) # Product(Книга, 500)
print(p) # Вызывает __str__
call
Делает объект вызываемым как функция:
class Multiplier:
def __init__(self, factor):
self.factor = factor
def __call__(self, x):
return x * self.factor
multiply_by_3 = Multiplier(3)
print(multiply_by_3(5)) # 15
print(multiply_by_3(10)) # 30
enter и exit
Позволяют использовать объект в with блоке:
class FileManager:
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
self.file = None
def __enter__(self):
self.file = open(self.filename, self.mode)
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
if self.file:
self.file.close()
return False # Не подавляем исключения
with FileManager("test.txt", "w") as f:
f.write("Hello")
# Файл автоматически закроется
hash и eq для dict ключей
class User:
def __init__(self, id, name):
self.id = id
self.name = name
def __hash__(self):
return hash(self.id)
def __eq__(self, other):
return self.id == other.id
user1 = User(1, "Alice")
user2 = User(1, "Alice")
users_dict = {user1: "Info1"}
print(users_dict[user2]) # Info1 (работает, потому что hash и eq согласованы)
getattr и setattr
class DynamicObject:
def __getattr__(self, name):
# Вызывается если атрибута нет
return f"Атрибут {name} не существует"
def __setattr__(self, name, value):
# Вызывается при присваивании
print(f"Устанавливаю {name}={value}")
super().__setattr__(name, value)
obj = DynamicObject()
obj.x = 5 # Вызовет __setattr__
print(obj.y) # Вызовет __getattr__
Резюме
Служебные методы dict — это мощный инструмент для создания объектов, которые работают как встроенные типы. Они позволяют переопределять поведение операторов, сравнений, индексации и многого другого. Понимание dunder методов критично для написания Pythonic кода и создания удобных API.