В Python магические методы позволяют вам определять специальное поведение для экземпляров вашего класса. Одними из наиболее полезных являются методы, которые отвечают за доступ, изменение и удаление элементов по индексу или ключу: __getitem__
, __setitem__
и __delitem__
. Эти методы дают возможность экземплярам вашего класса вести себя подобно спискам, словарям и другим стандартным коллекциям Python.
__getitem__
Метод __getitem__
отвечает за доступ к элементам экземпляра класса по индексу или ключу. По умолчанию, если у объекта нет этого метода, попытка обращения по индексу приводит к ошибке TypeError: 'Object' object is not subscriptable
. Это значит, что объект не поддерживает операцию индексирования, как это делают списки и словари.
Допустим, мы создаем класс Matrix
, который содержит двумерный массив значений. Мы хотим обращаться к элементам матрицы по индексу, например, matrix[1][2]
, но без __getitem__
это невозможно:
class Matrix:
def __init__(self, values):
self.values = values
matrix = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(matrix[1][2]) # Ошибка TypeError
Для того чтобы этот код работал, нужно определить метод __getitem__
:
class Matrix:
def __init__(self, values):
self.values = values
def __getitem__(self, index):
if isinstance(index, int) and 0 <= index < len(self.values):
return self.values[index]
else:
raise IndexError("Индекс вне границ матрицы")
matrix = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(matrix[1][2]) # Вывод: 6
В данном примере __getitem__
проверяет, что индекс в пределах допустимого диапазона, а затем возвращает нужную строку матрицы. Если передать недопустимый индекс, то возбуждается исключение IndexError
.
Теперь добавим поддержку обращения к элементам матрицы по строковому ключу: если передается строка, мы будем использовать ее длину как индекс:
class Matrix:
def __init__(self, values):
self.values = values
def __getitem__(self, index):
if isinstance(index, int) and 0 <= index < len(self.values):
return self.values[index]
elif isinstance(index, str):
index = len(index)
if 0 <= index < len(self.values):
return self.values[index]
else:
raise IndexError("Индекс вне границ матрицы")
else:
raise TypeError("Недопустимый тип индекса")
matrix = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(matrix["abc"]) # Вывод: [4, 5, 6] (длина строки "abc" равна 3)
__setitem__
Метод __setitem__
позволяет изменять значения в объекте по индексу или ключу. Он вызывается при присваивании значения с помощью синтаксиса obj[index] = value
. Рассмотрим, как можно изменить значения элементов в матрице:
class Matrix:
def __init__(self, values):
self.values = values
def __getitem__(self, index):
return self.values[index]
def __setitem__(self, index, value):
if isinstance(index, int) and 0 <= index < len(self.values):
self.values[index] = value
elif isinstance(index, str):
index = len(index)
if 0 <= index < len(self.values):
self.values[index] = value
else:
raise IndexError("Индекс вне границ матрицы")
else:
raise TypeError("Недопустимый тип индекса")
matrix = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
matrix[1] = [10, 11, 12]
matrix["four"] = [13, 14, 15]
print(matrix.values) # Вывод: [[1, 2, 3], [10, 11, 12], [13, 14, 15]]
__delitem__
Метод __delitem__
позволяет удалять элементы по индексу или ключу. Он вызывается при использовании оператора del obj[index]
. По умолчанию, метод удаляет элемент по указанному индексу. Однако мы можем модифицировать его так, чтобы удалялись все элементы, равные переданному значению:
class Matrix:
def __init__(self, values):
self.values = values
def __getitem__(self, index):
return self.values[index]
def __setitem__(self, index, value):
self.values[index] = value
def __delitem__(self, key):
if isinstance(key, int):
del self.values[key]
elif isinstance(key, list):
for value in key:
while value in self.values:
self.values.remove(value)
else:
raise TypeError("Неверный тип ключа")
matrix = Matrix([3, 4, 4, 5, 6, 4])
del matrix[4] # Удаляет элемент с индексом 4
print(matrix.values) # Вывод: [3, 4, 4, 5, 4]
del matrix[[4, 5]] # Удаляет все четверки и пятерки
print(matrix.values) # Вывод: [3]
В этом примере __delitem__
может принимать список значений и удаляет все вхождения элементов, указанных в этом списке. Это позволяет выполнять более сложные операции удаления.
Вот таблица по лекции о методах __getitem__
, __setitem__
, и __delitem__
:
Тема | Описание |
---|---|
Метод __getitem__ | Отвечает за доступ к элементам объекта по индексу или ключу. Если метод не реализован, объект не поддерживает индексирование (TypeError). |
Пример использования | В классе Matrix метод __getitem__ позволяет обращаться к элементам матрицы по индексу, как в списке: matrix[1][2] . |
Поддержка строковых ключей | Метод может обрабатывать строковые индексы, где длина строки используется в качестве индекса: matrix["abc"] (длина строки "abc" равна 3). |
Метод __setitem__ | Позволяет изменять значения элементов по индексу или ключу с помощью синтаксиса obj[index] = value . |
Пример изменения значений | В классе Matrix можно менять значения как по целочисленным, так и по строковым индексам: matrix[1] = [10, 11, 12] , matrix["four"] = [13, 14, 15] . |
Метод __delitem__ | Удаляет элементы по индексу или ключу. Вызывается при использовании оператора del obj[index] . |
Пример удаления элементов | В классе Matrix метод может удалять элементы по индексу (del matrix[4] ) или по списку значений (del matrix[[4, 5]] , удаляются все четверки и пятерки). |
Итог | Методы __getitem__ , __setitem__ , и __delitem__ позволяют кастомным классам работать с элементами как стандартные коллекции, упрощая доступ, изменение и удаление. |
Таблица охватывает основные моменты лекции и примеры использования этих магических методов в Python.
Магические методы __getitem__
, __setitem__
и __delitem__
дают гибкость для работы с кастомными классами, позволяя им вести себя как стандартные коллекции. Это упрощает доступ к элементам, их изменение и удаление, а также предоставляет возможности для сложных логических операций.
Попробуйте самостоятельно реализовать аналогичные методы для других структур данных, чтобы лучше понять их применение!