Оператор del в Python

del — это специальный оператор Python для удаления имени из текущей области видимости или элемента из контейнера. Это не функция, а синтаксическая конструкция, поэтому пишется без скобок:

x = 42
del x
print(x)   # NameError: name 'x' is not defined

Что del делает на самом деле

В Python переменная — это имя, привязанное к объекту. del x не «уничтожает» объект — он только удаляет имя. Сам объект уйдёт, только когда на него не останется ни одной ссылки. Тогда сборщик мусора освободит память.

до del:
    x ---> [объект 42]
    y ---> [объект 42]
после del x:
              [объект 42]   <- никуда не удалился, на него ссылается y
    y ---^

после del y:
              [объект 42]   <- ссылок нет, GC освобождает

Зачем использовать del

В реальном коде del нужен редко. Основные сценарии:

  1. Удаление элементов из контейнеров — основное применение.

  2. Очистка имени до конца функции — например, чтобы случайно не использовать уже отработавший объект.

  3. Удаление атрибутов объекта.

  4. Помощь GC с большими объектами — в редких случаях, когда нужно срочно освободить память (но обычно это делает сам сборщик).


Удаление переменной

name = 'Айдос'
print(name)        # Айдос
del name
print(name)        # NameError

После del имя name исчезает из локальной таблицы имён.


Удаление элемента списка

Самое частое и полезное применение del — выкинуть элемент из списка по индексу или срезу.

nums = [10, 20, 30, 40, 50]

del nums[2]
print(nums)     # [10, 20, 40, 50]

del nums[1:3]
print(nums)     # [10, 50]

del nums[:]     # очистить весь список (в отличие от del nums — список останется живым)
print(nums)     # []

Сравним с альтернативами:

del nums[i]          - удалить по индексу
nums.pop(i)          - удалить по индексу И вернуть значение
nums.remove(value)   - удалить ПЕРВОЕ вхождение значения

Удаление элемента словаря

user = {'id': 1, 'name': 'Айдос', 'token': 'secret'}

del user['token']
print(user)
# {'id': 1, 'name': 'Айдос'}

Если ключа нет, будет KeyError. Альтернатива — user.pop('token', None), которая не бросает исключение.


Удаление атрибута объекта

class User:
    pass

u = User()
u.name = 'Айдос'
u.age = 21

del u.age
print(u.name)    # Айдос
print(u.age)     # AttributeError

Практический пример: чистка кэша

Допустим, у нас есть простой кэш-словарь, и по сигналу нужно почистить устаревшие записи:

import time

cache = {}

def get(key):
    value, expires = cache.get(key, (None, 0))
    if expires < time.time():
        cache.pop(key, None)
        return None
    return value

def cleanup():
    now = time.time()
    expired = [k for k, (_, exp) in cache.items() if exp < now]
    for k in expired:
        del cache[k]

Здесь del cache[k] удаляет конкретные ключи. Обратите внимание: мы сначала собрали список устаревших, и только потом удаляем — нельзя менять словарь во время итерации по нему.


Практический пример: явное освобождение большого объекта

def process(path):
    big_data = load_huge_file(path)   # пусть это 2 ГБ
    result = analyze(big_data)
    del big_data                       # отпустили память
    return heavy_postprocess(result)

После del big_data сборщик мусора может освободить память сразу, не дожидаясь конца функции. На практике это полезно только при работе с очень крупными данными.


del vs = None

Часто возникает вопрос: чем del x отличается от x = None? Оба удаляют ссылку на объект, но эффект разный:

del x       -> имя x исчезает совсем
x = None    -> имя x остаётся, но указывает на None

Если планируете дальше пользоваться именем — лучше = None. Если имя больше не нужно — del.


Подводные камни

Предупреждение

  • ``del`` не освобождает память сразу. Он удаляет имя/ссылку. Объект удалится позже, когда не останется ни одной ссылки.

  • Нельзя удалять имена из замыкания. Внутри вложенной функции del для переменной внешней области даст SyntaxError, если переменная не объявлена через nonlocal.

  • ``del`` внутри цикла по списку — опасно. for x in nums: del x ничего разумного не делает. for i, x in enumerate(nums): del nums[i] испортит индексы. Всегда собирайте кандидатов отдельно и удаляйте после цикла.

  • ``del`` для глобального имени внутри функции требует global.


Смотрите также


Примечание

Лицензия и источники

Часть материала адаптирована из официальной документации Python (https://docs.python.org/3/reference/simple_stmts.html#the-del-statement), доступной под Python Software Foundation License Version 2 (PSF License). Адаптация, переработка, оригинальные примеры и пояснения — © AlashEd Wiki.