Как сделать del в python
del от delete (англ.) — удалить.
del name
del name[i]
del name[i:j:k]
del name.attribute
На заметку
В первой форме name — это имя переменной, взятое буквально. В последних трех формах name может являться выражением.
- Удаление нескольких целей рекурсивно удаляет каждую цель слева направо.
- Удаление имени удаляет привязку этого имени из локального или глобального пространства имен (в зависимости от того, были ли определено имя при помощи инструкции global в том же блоке кода). Если имя не привязано, возбуждается исключение NameError.
- Удаление ссылок на атрибуты, элементов и срезов передаётся базовому объекту (носителю) и осуществляется им. Удаление среза, в целом, эквивалентно присвоению пустого среза (однако и оно определяется самим объектом среза).
| del variable | удаление переменной |
| del obj.attr | удаление атрибута |
| del data[k] | удаление элемента по индексу |
| del data[i:j] | удаление элементов по срезу |
my_list = [123, 'spam', 1.23, 'NI']
del my_list[2]
my_list # [123, 'spam', 'NI']
another_list = ['abc', my_list, 42]
del another_list[1][2] # удаляем ‘NI’ из вложенного списка my_list
my_list # [123, 'spam']
list_one = ['spam', 1, 11, 111]
list_two = [2, 22, 'spam', 222]
list_three = [3, 'spam', 33, 333]
del list_one[0], list_two[2], list_three[1] # удаляем spam одновременно из трёх списков
+py3.2: Разрешено удаление имени из локального пространства имён, если оно используется во вложенном блоке как несвязанное (не было определено в рамках того же блока). Ранее в таких случаях возбуждалось SyntaxError:
def print_done():
some = 'some'
del some
# До Python 3.2 в подобных случаях инструкция вызывает SyntaxError:
# can not delete variable 'some' referenced in nested scope
def print_some():
print(some)
print('done')
print_done()
Деструктор в Python: уничтожение объектов
Деструктор в Python – это специальный метод, который вызывается при уничтожении объекта. Конструктор же, наоборот, используется для создания и инициализации объекта класса.
В этой статье мы разберем:
- как создать деструктор в Python
- использование метода __del__()
- как работает деструктор.
Что такое деструктор в Python?
В объектно-ориентированном программировании деструктор вызывается при удалении или уничтожении объекта. Деструктор используется для выполнения действий по очистке перед разрушением объекта, таких как закрытие соединений с базой данных или дескриптор файла.
В Python есть сборщик мусора, который автоматически обрабатывает управление памятью. Например, он очищает память, когда объект выходит за пределы области видимости.
Однако при уничтожении объекта необходимо освобождать не только память. Мы должны освободить или закрыть другие ресурсы, которые использовались объектом, такие как открытые файлы, соединения с базой данных, очистка буфера или кеша. Для выполнения всех этих задач очистки мы используем деструктор в Python.
Деструктор противоположен конструктору. Конструктор используется для инициализации объектов, а деструктор — для удаления или уничтожения объектов, в результате чего освобождается ресурс, занятый этими объектами.
В Python деструктор вызывается не вручную, а полностью автоматически. Это происходит в следующих двух случаях:
- когда объект выходит за пределы области видимости
- когда счетчик ссылок на объект достигает 0.
Для определения деструктора используется специальный метод __del__() . Например, когда мы выполняем del имя_объекта , деструктор вызывается автоматически, и объект собирается в мусор.
Создание деструктора с помощью метода __del__()
Магический метод __del__() используется как деструктор в Python. Метод __del__() будет неявно вызываться, когда все ссылки на объект будут удалены, то есть когда объект подходит для сборщика мусора.
Этот метод автоматически вызывается в Python, когда экземпляр собираются уничтожить. Его также называют финализатором или (неправильно) деструктором.
Синтаксис объявления деструктора будет следующим:
def __del__(self): # тело деструктора
- def – ключевое слово, которое используется для определения метода.
- __del__() – зарезервированный метод. Он вызывается, как только все ссылки на объект будут удалены.
- self : первый аргумент self относится к текущему объекту.
Примечание. Аргументы метода __del__() необязательны. Мы можем определить деструктор с любым количеством аргументов.
Пример
Давайте рассмотрим создание деструктора в Python на простом примере. Мы создадим класс Student с деструктором.
class Student: # конструктор def __init__(self, name): print('Inside Constructor') self.name = name print('Object initialized') def show(self): print('Hello, my name is', self.name) # деструктор def __del__(self): print('Inside destructor') print('Object destroyed') # создать объект s1 = Student('Emma') s1.show() # удалить объект del s1
Запустим наш код и получим следующий результат:
Inside Constructor Object initialized Hello, my name is Emma Inside destructor Object destroyed
Примечание. Как видно из вывода, при удалении ссылки на объект с помощью del s1 метод __del__() вызывается автоматически.
В приведенном выше коде мы создали один объект. s1 – это ссылочная переменная, указывающая на вновь созданный объект.
Деструктор вызывается, когда ссылка на объект удалена или счетчик ссылок на объект доходит до нуля.
Важные моменты, которые следует помнить о деструкторе
- Метод __del__() вызывается для любого объекта, когда счетчик ссылок для этого объекта становится равным нулю.
- Счетчик ссылок для данного объекта становится нулевым, когда работа программы завершается, или мы удаляем все ссылки вручную с помощью ключевого слова del .
- Деструктор не будет запускаться при удалении какой-то одной ссылки на объект. Он будет вызываться только тогда, когда все ссылки на объект будут удалены.

Пример
Давайте разберемся в приведенных выше пунктах на примере.
Сначала создадим объект класса Student , используя s1 = student (‘Emma’) .
Затем давайте создадим новую ссылку на объект, присвоив переменной s2 значение s1 (т.е. s2 = s1 ).
Теперь обе ссылочные переменные s1 и s2 указывают на один и тот же объект.
От редакции Pythonist. Ссылки, имена и значения подробно рассмотрены в статье «Факты и мифы об именах и значениях в Python».
Далее мы удалим ссылку s1 .
Затем добавим 5 секунд задержки (sleep) к основному потоку, чтобы было ясно, что деструкторы вызываются только при удалении всех ссылок на объекты.
import time class Student: # конструктор def __init__(self, name): print('Inside Constructor') self.name = name def show(self): print('Hello, my name is', self.name) # деструктор def __del__(self): print('Object destroyed') # создание объекта s1 = Student('Emma') # создание новой ссылки # обе ссылки указывают на один объект s2 = s1 s1.show() # удаление ссылки s1 del s1 # добавление задержки и наблюдение за результатом time.sleep(5) print('After sleep') s2.show()
Inside Constructor Hello, my name is Emma
After sleep Hello, my name is Emma Object destroyed
- Как вы можете видеть из полученного результата, деструкторы вызываются только тогда, когда удаляются все ссылки на объекты.
- Кроме того, деструктор выполняется, когда код (программа) заканчивается и объект становится доступным для сборщика мусора. Например, мы не удаляли ссылку на объект s2 вручную с помощью del s2 . Это произошло автоматически, т.к. программа закончилась.
Случаи, когда деструктор работает не корректно
__del__() не является идеальным решением для очистки ненужных объектов. В Python деструктор ведет себя странно и не выполняется в следующих двух случаях:
- ссылка является круговой: два объекта ссылаются друг на друга
- исключение в методе __init__()
Круговая ссылка
__del__() некорректно работает в случае циклической ссылки.Суть этой ссылки в том, что два объекта ссылаются друг на друга. И когда оба объекта выходят за пределы области видимости, Python не знает, какой объект уничтожить первым. Поэтому, чтобы избежать ошибок, он не уничтожает ни один из них.
Короче говоря, это означает, что сборщик мусора не знает порядок, в котором объекты должны быть уничтожены, поэтому он не удаляет их из памяти.
В идеале деструктор должен выполняться, когда объект выходит за пределы области видимости или его счетчик ссылок достигает нуля. Но объекты, связанные круговой ссылкой, будут храниться в памяти до тех пор, пока приложение будет работать.
Пример
В приведенном ниже примере в идеале оба объекта — Vehicle и Car — должны быть уничтожены сборщиком мусора после выхода за пределы области видимости. Тем не менее, из-за циклической ссылки они остаются в памяти.
Для управления ресурсами, которые необходимо очистить, можно посоветовать использовать оператор with .
import time class Vehicle(): def __init__(self, id, car): self.id = id; # сохранение ссылки объекта Car self.dealer = car; print('Vehicle', self.id, 'created'); def __del__(self): print('Vehicle', self.id, 'destroyed'); class Car(): def __init__(self, id): self.id = id; # сохранение объекта класса Vehicle в переменной 'dealer' # пересылка ссылки объекта Car ('self') для объекта Vehicle self.dealer = Vehicle(id, self); print('Car', self.id, 'created') def __del__(self): print('Car', self.id, 'destroyed') # создание объекта car c = Car(12) # удаление объекта car del c # в идеале теперь должен выполниться деструктор # задержка для наблюдения за поведением time.sleep(8)
Запустим наш код и получим следующее:
Vehicle 12 created Car 12 created
Исключение в методе __init__()
В объектно-ориентированном программировании конструктор – это специальный метод, используемый для создания и инициализации объекта класса. Используя метод __init__() , мы можем реализовать конструктор для инициализации объекта.
В ООП, если в конструкторе возникает какое-либо исключение при инициализации объекта, конструктор уничтожает объект.
Аналогично, в Python, если в методе инициализации возникает какое-либо исключение при инициализации объекта, вызывается метод del . Но на самом деле объект не создается, и ему не выделяются ресурсы.
Несмотря на то, что объект так и не был инициализирован правильно, метод del все равно попытается очистить все ресурсы. А это, в свою очередь, может привести к другому исключению.
Пример
class Vehicle: def __init__(self, speed): if speed > 240: raise Exception('Not Allowed'); self.speed = speed; def __del__(self): print('Release resources') # создание объекта car = Vehicle(350); # для явного удаления объекта: del car
Запустив этот код, мы получим следующий результат:
Traceback (most recent call last): Release resources Exception: Not Allowed
Заключение
В объектно-ориентированном программировании деструктор вызывается при удалении или уничтожении объекта.
Деструктор используется для выполнения действий по очистке перед разрушением объекта, таких как закрытие соединений с базой данных.
Для выполнения задачи очистки перед удалением объекта в Python мы используем метод __del__() .
При удалении ссылки на объект деструктор не запускается. Для этого нужно удалить все ссылки на этот объект.
Инструкция del
Несмотря на свое название, инструкция del не удаляет объекты в буквальном смысле, она лишь открепляет ссылки, разрывая связь между именем и объектом. Удаление объекта произойдет как следствие работы сборщика мусора в отношении объектов, на которые больше не ссылается ни один другой объект.
- del variable — удаление переменной,
- del obj.attr — удаление атрибута,
- del data[k] — удаление элемента по индексу или ключу в случае словаря,
- del data[i:j] — удаление элементов по срезу.
Инструкция del состоит из ключевого слова del , за которым следует одна или несколько целевых ссылок, разделенных запятыми. Каждая целевая ссылка может быть переменной, ссылкой на атрибут, индексированным элементом или срезом и должна быть связана с каким-либо объектом. Если целевая ссылка является переменной, выполнение инструкции del означает разрыв связи между объектом и закрепленной за ним переменной. Если эта операция запрашивается, она всегда выполняется.
Во всех остальных случаях инструкция del определяет запрос к объекту на открепление одного или нескольких его атрибутов или элементов. Объект может отказать в выполнении этой операции по отношению к некоторым/всем атрибутам или элементам, бросая исключение при попытке отмены связывания в тех случаях, когда это запрещено.
Контейнерам разрешено сопровождать выполнение инструкции del побочными эффектами. Например, предположим что array — это словарь и инструкция del array[2] успешно выполнена, то это означает, что следующие обращения к элементу array[2] будут недопустимыми и приведут к возбуждению исключения KeyError . Такое поведение будет до тех пор, пока array[2] вновь не присвоим некоторое значение. Но если array — это список, то в результате выполнения инструкции del array[2] каждый последующий элемент сместится на одну позицию влево и последующие обращения к array[2] будут по прежнему действительными, хотя будут давать другое значение.
Пример:
a = [1, ‘not’, 10, ‘in’] del a[2] print(a) # [1, ‘not’, ‘in’] b = [‘foo’, ‘array’, 20] x = b.append(a) # удаляем из вложенного списка del b[3][2] print(b) # [‘foo’, ‘array’, 20, [1, ‘not’]] one = [‘foo’, 1, 2, 3] two = [10, 20, ‘foo’, 30] three = [11, ‘foo’, 22, 33] # удаляем одновременно из всех списков del one[0], two[2], three[1] print(one, two, three) # [1, 2, 3] [10, 20, 30] [11, 22, 33] x = ‘year’: «2020», ‘month’: «01», ‘day’: «01»> y = ‘artist’: «Beethoven», ‘title’: ‘Symphony No 5’> del x[‘day’], y[‘artist’] print(x, y) #
Python: все про del

Инструкция del (от англ. delete), как можно понять из названия, нужна чтобы что-то удалять, а именно имена переменных, атрибуты объектов, элементы списков и ключи словарей.
1. Удаление элемента из списка по индексу:
>>> x = [1, 2, 3, 4, 5] >>> del x[2] >>> x [1, 2, 4, 5]
Также можно удалять по срезам. Пример: удаление первых двух элементов:
>>> x = [1, 2, 3, 4, 5] >>> del x[:2] >>> x [3, 4, 5]
Удаление последних n элементов: del x[n:] .
Удаление элементов с четными индексами: del x[::2] , нечетными: del x[1::2] .
Удаление произвольного среза: del x[i:j:k] .
Не путайте del x[2] и x.remove(2) . Первый удаляет по индексу (нумерация с 0), а второй по значению, то есть находит в списке первую двойку и удаляет ее.
2. Удаление ключа из словаря. Просто:
>>> d = >>> del d[«foo»] >>> d
А вот строки, байты и сеты del не поддерживают.
3. Удаление атрибута объекта.
class Foo: def __init__(self): self.var = 10 f = Foo() del f.var print(f.var) # ошибка!
Примечание: можно через del удалить метод у самого класса del Foo.method , но нельзя удалить метод у экземпляра класса del Foo().method – AttributeError.
4. Что значит удалить имя переменной? Это просто значит, что надо отвязать имя от объекта (при этом если на объект никто более не ссылается, то он будет освобожден сборщиком мусора), а само имя станет свободно. При попытке доступа к этому имени после удаления будет NameError, пока ему снова не будет что-то присвоено.
>>> a = 5 >>> del a >>> a Traceback (most recent call last): File "", line 1, in NameError: name 'a' is not defined
Здесь кроется один нюанс. Если переменная была внутри функции помечена, как global, то после ее удаления глобальная переменная никуда не денется, а имя освободится лишь в зоне видимости функции. Причем если мы снова присвоим ей значение, то она опять окажется глобальной, т.е. del не очищает информацию о global!
g = 100 def f(): global g g = 200 del g # g останется вне функции g = 300 # та же самая глобальная g f() print(g) # 300
Чтобы реально удалить глобальную переменную, можно сделать так: del globals()[‘g’] .
В пунктах 1, 2, 3 в качестве имен могут фигурировать выражения и ссылки, так как операции идут над содержимым объектов, а в пункте 4 должно быть строго формальное имя удаляемого объекта.
>>> x = [1, 2, 3] >>> y = x >>> del y # удаляет именно y, но x остается
Еще одна особенность del – она может удалить несколько вещей за раз, если передать в нее кортеж или список объектов на удаление.
x, y, z = 10, 20, [1, 2, 3] del x, y, z[2]
Пусть задан список из 5 элементов:
x = [1, 2, 3, 4, 5] del x[2], x[4]
Казалось бы, что будут удалены 2-й и 4-й элементы списка, но это не так! Удаления происходят один за одним, и сначала будет удален 2-й элемент, размер списка уменьшится на 1, а потом будет попытка удалить 4-й элемент, но она будет неудачна – вылетит исключение IndexError, потому что элемента с индексом 4 больше нет, а сам список будет равен [1, 2, 4, 5]. Так что будьте внимательны в подобных ситуациях!
Специально для канала @pyway. Подписывайтесь на мой канал в Телеграм @pyway
