- Деструктор в Python: уничтожение объектов
- Что такое деструктор в Python?
- Создание деструктора с помощью метода __del__()
- Пример
- Важные моменты, которые следует помнить о деструкторе
- Пример
- Случаи, когда деструктор работает не корректно
- Круговая ссылка
- Пример
- Исключение в методе __init__()
- Пример
- Заключение
- Как очистить консоль в Python
- Способ 1: использование модуля os
- Способ 2: с помощью функции subprocess.call()
- Способ 3: использование escape-кодов ANSI
- Способ 4: применение пакета ipykernel в блокнотах Jupyter
- Как очистить экран оболочки в Python
Деструктор в 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__() .
При удалении ссылки на объект деструктор не запускается. Для этого нужно удалить все ссылки на этот объект.
Как очистить консоль в Python
В данном руководстве рассмотрим различные способы очистки консоли в Python.
Способ 1: использование модуля os
Используйте команду os.system(‘clear’) для очистки консоли на Mac и Linux в Python и команду os.system(‘cls’) для очистки консоли на платформе Windows. Для программной очистки консоли в Python необходимо импортировать модуль os и использовать его метод os.system(). os — это встроенная библиотека, которая поставляется вместе с установкой Python3.
Я использую Mac, поэтому мне нужно писать команды, связанные с Linux.
Если вы запустите приведенную выше команду в своей консоли, она очистит экран.
Для пользователя Windows используйте следующий код.
Вы можете использовать лямбда-функцию, если не хотите использовать полную.
Способ 2: с помощью функции subprocess.call()
Вы можете использовать функцию subprocess.call() в модуле подпроцесса, которая позволяет создавать новые процессы, подключаться к их каналам ввода/вывода/ошибки и очищать консоль в Python.
Если вы запустите приведенный выше код, он очистит консоль.
Способ 3: использование escape-кодов ANSI
Escape-коды ANSI — это последовательности символов, которые можно включить в строку, чтобы указать различные типы форматирования вывода терминала, например, изменить цвет или положение курсора или очистить консоль.
Код очистит консоль Python.
«\033» — управляющий символ, а c — код для сброса терминала.
Аргумент «end» устанавливается в пустую строку, чтобы гарантировать, что после escape-кода не будет добавлен дополнительный разрыв строки.
Способ 4: применение пакета ipykernel в блокнотах Jupyter
В блокнотах Jupyter вы можете очистить вывод ячейки с помощью пакета ipykernel.
Пакет ipykernel предоставляет API для управления ядром Jupyter, включая возможность очистки вывода ячейки или, в нашем случае, программной консоли.
Как очистить экран оболочки в Python
Иногда, работая с оболочкой Python, мы получали случайный вывод или писали ненужные операторы, и мы хотим очистить экран по какой-то причине.
Как очистить экран оболочки в Python? Для очистки терминала (окна терминала) используются команды «cls» и «clear». Если вы используете оболочку в IDLE, на нее такие команды не повлияют. К сожалению, в IDLE нет возможности очистить экран. Лучшее, что вы могли сделать, – это прокрутить экран вниз на множество строк.
Хотя вы можете поместить это в функцию:
А затем при необходимости вызовите его как функцию cls(). Это очистит консоль; все предыдущие команды исчезнут, и экран начнется с самого начала.
Если вы используете Linux, то –
Import os # Type os.system('clear')
Если вы используете Windows-
Import os #Type os.system('CLS')
Мы также можем сделать это с помощью скрипта Python. Рассмотрим следующий пример.
# import os module from os import system, name # sleep module to display output for some time period from time import sleep # define the clear function def clear(): # for windows if name == 'nt': _ = system('cls') # for mac and linux(here, os.name is 'posix') else: _ = system('clear') # print out some text print('Hello\n'*10) # sleep time 2 seconds after printing output sleep(5) # now call function we defined above clear()
Примечание. Используется переменная подчеркивания, потому что оболочка Python всегда сохраняет свой последний вывод в подчеркивании.