Когда-дель-полезное в Python?


Я не могу действительно думать о какой-либо причине, почему python нуждается в del ключевое слово (и большинство языков, кажется, нет подобного сайта). Например, вместо удаления переменной можно просто назначить None к нему. А при удалении из словаря, a del метод может быть добавлен.

есть ли причина, чтобы держать del в python, или это остаток дней предварительной сборки мусора Python?

17 280

17 ответов:

во-первых, вы можете del другие вещи, кроме локальных переменных

del list_item[4]
del dictionary["alpha"]

оба из которых должны быть явно полезным. Во-вторых, используя del на локальную переменную делает цель яснее. Сравните:

del foo

до

foo = None

Я знаю в случае del foo что цель состоит в том, чтобы удалить переменную из области видимости. Это не ясно, что foo = None это делает. Если кто-то просто назначил foo = None я мог бы подумать, что это был мертвый код. Но я сразу знаю, что кто-то, кто кодирует del foo пытался сделать.

вот эта часть, что del делает (с Ссылка На Язык Python):

удаление имени удаляет привязку этого имени локального или глобального пространства имен

назначение None к имени не удаляет привязку имени из пространства имен.

(Я полагаю, что могут быть некоторые дебаты о том, действительно ли удаление привязки имени полезное, но это уже другая вопрос.)

одно место я нашел del полезно очищать посторонние переменные в циклах for:

for x in some_list:
  do(x)
del x

теперь вы можете быть уверены, что x будет неопределенным, если вы используете его вне цикла for.

просто еще одна мысль.

при отладке http-приложений в рамках, таких как Django, стек вызовов, полный бесполезных и перепутанных ранее используемых переменных, особенно когда это очень длинный список, может быть очень болезненным для разработчиков. таким образом, на этом этапе управление пространством имен может быть полезно.

есть конкретный пример, когда вы должны использовать del (могут быть и другие, но я знаю об этом от силы), когда вы используете sys.exc_info() для проверки исключения. Эта функция возвращает кортеж, тип исключения, сообщение и трассировки.

первые два значения обычно достаточны для диагностики ошибки и действия на нее, но третий содержит весь стек вызовов между тем, где было вызвано исключение и где исключение пойманный. В частности, если вы делаете что-то вроде

try:
    do_evil()
except:
    exc_type, exc_value, tb = sys.exc_info()
    if something(exc_value):
        raise

укажите, tb заканчивается в локальных точках стека вызовов, создавая циклическую ссылку, которая не может быть собрана в мусор. Таким образом, важно сделать:

try:
    do_evil()
except:
    exc_type, exc_value, tb = sys.exc_info()
    del tb
    if something(exc_value):
        raise

чтобы разорвать циклическую ссылку. Во многих случаях, когда вы хотели бы позвонить sys.exc_info(), как и в случае с магией метакласса, трассировка и полезно, Так что вы должны убедиться, что вы очистить его вверх прежде чем вы можете оставить обработчик исключений. Если вам не нужна обратная трассировка, вы должны немедленно удалить ее или просто сделать:

exc_type, exc_value = sys.exc_info()[:2]

чтобы избежать всего этого вместе.

удаление переменной отличается от ее установки в None

удаление имен переменных с помощью del вероятно, что-то используется редко, но это то, что не может быть тривиально достигнуто без ключевого слова. Если вы можете создать имя переменной, написав a=1, это хорошо, что вы теоретически можете отменить это удаление.

это может сделать отладку проще в некоторых случаях, как попытка получить доступ к удаленной переменной вызовет NameError.

вы можно удалить атрибуты экземпляра класса

Python позволяет писать что-то вроде:

class A(object):
    def set_a(self, a):
        self.a=a
a=A()
a.set_a(3)
if hasattr(a, "a"):
    print("Hallo")

если вы решите динамически добавлять атрибуты к экземпляру класса, вы, безусловно, хотите иметь возможность отменить его, написав

del a.a

принудительное закрытие файла после использования numpy.нагрузка:

использование ниши, возможно, но я нашел его полезным при использовании numpy.load читать файл. Время от времени я буду обновлять файл и нужно скопировать файл с тем же именем в каталог.

Я del чтобы освободить файл и позвольте мне скопировать в новый файл.

обратите внимание, я хочу, чтобы избежать with менеджер контекста, как я играл вокруг с сюжетами на команду линия и не хотел нажимать вкладку много!

посмотреть этой вопрос.

использование "del" явно также является лучшей практикой, чем присвоение переменной None. Если вы попытаетесь удалить переменную, которая не существует, вы получите ошибку времени выполнения, но если вы попытаетесь установить переменную, которая не существует, в None, Python молча установит новую переменную в None, оставив переменную, которую вы хотели удалить, где она была. Так что дел поможет вам поймать свои ошибки раньше

чтобы добавить несколько пунктов к вышеприведенным ответам: del x

определение x указывает r - > o (ссылка r, указывающая на объект o), но del x изменяет r, а не o. это операция над ссылкой (указателем) на объект, а не объект, связанный с x. различение r и o является ключевым здесь.

  • он удаляет его из locals()
  • удаляет его из globals() если это x принадлежит там.
  • удаляет его из стека фрейм (удаляет ссылку физически из него, но сам объект находится в пуле объектов, а не в кадре стека).
  • удаляет его из текущей области. Очень полезно ограничить диапазон определения локальной переменной, что в противном случае может вызвать проблемы.
  • речь идет скорее об объявлении имени, а не об определении содержания.
  • это влияет, где x принадлежит, а не где x указывает. Единственное физическое изменение в памяти заключаться в следующем. Например, если x находится в словаре или списке, он (как ссылка) удаляется оттуда(и не обязательно из пула объектов). В этом примере словарь, к которому он принадлежит, является фреймом стека (locals()), который перекрывается с глобалами ().

когда del полезен в python?

вы можете использовать его для удаления одного элемента массива вместо синтаксиса среза x[i:i+1]=[]. Это может быть полезно, если например вы находитесь в os.walk и хотите удалить элемент в каталоге. Я бы не считал ключевое слово полезным для этого, хотя, так как можно просто сделать [].remove(index) метод (the .remove метод на самом деле поиск и удаление первого экземпляра значения).

что del может быть использован для, Я считаю это полезным Я ситуации, как это:

def f(a, b, c=3):
    return '{} {} {}'.format(a, b, c)

def g(**kwargs):
    if 'c' in kwargs and kwargs['c'] is None:
        del kwargs['c']

    return f(**kwargs)

# g(a=1, b=2, c=None) === '1 2 3'
# g(a=1, b=2) === '1 2 3'
# g(a=1, b=2, c=4) === '1 2 4'

эти две функции могут быть в разных пакетах/модули и программисту не нужно знать, какой аргумент значение по умолчанию c на f на самом деле есть. Поэтому, используя kwargs в сочетании с del, вы можете сказать: "я хочу значение по умолчанию на c", установив его в None (или в этом случае также оставьте его).

вы могли бы сделать то же самое с что-то вроде:

def g(a, b, c=None):
    kwargs = {'a': a,
              'b': b}
    if c is not None:
        kwargs['c'] = c

    return f(**kwargs)

однако я нахожу предыдущий пример более сухим и элегантным.

del часто видела в __init__.py файлы. Любая глобальная переменная, определенная в __init__.py файл автоматически "экспортируется" (он будет включен в from module import *). Один из способов избежать этого-определить __all__, но это может стать грязным и не каждый использует его.

например, если у вас есть код __init__.py как

import sys
if sys.version_info < (3,):
    print("Python 2 not supported")

тогда ваш модуль будет экспортировать sys имя. Вместо этого вы должны написать

import sys
if sys.version_info < (3,):
    print("Python 2 not supported")

del sys

Я думаю, что одна из причин, по которой del имеет свой собственный синтаксис, заключается в том, что замена его функцией может быть трудной в некоторых случаях, учитывая, что она работает с привязкой или переменной, а не со значением, на которое она ссылается. Таким образом, если версия функции del должна быть создана, контекст должен быть передан. дель фу должен был бы стать глобалами ().удалить ('foo') или locals ().удалить ('foo'), который становится грязным и менее читаемым. Тем не менее я говорю, что избавиться от дел было бы хорошо, учитывая его, казалось бы, редкое использование. Но удаление языковых особенностей / недостатков может быть болезненным. Может быть, python 4 удалит его:)

еще одна ниша использования : В pyroot С помощью ROOT5 или ROOT6 "del" может быть полезно удалить объект python, который ссылается на уже не существующий объект C++. Это позволяет динамическому поиску pyroot найти объект C++ с одинаковым именем и привязать его к имени python. Таким образом, вы можете иметь такой сценарий, как:

import ROOT as R
input_file = R.TFile('inputs/___my_file_name___.root')
tree = input_file.Get('r')
tree.Draw('hy>>hh(10,0,5)')
R.gPad.Close()
R.hy # shows that hy is still available. It can even be redrawn at this stage.
tree.Draw('hy>>hh(3,0,3)') # overwrites the C++ object in ROOT's namespace
R.hy # shows that R.hy is None, since the C++ object it pointed to is gone
del R.hy
R.hy # now finds the new C++ object

Надеюсь, эта ниша будет закрыта с более разумным управлением объектами ROOT7.

однажды мне пришлось использовать:

del serial
serial = None

потому что с помощью только:

serial = None

не отпустил последовательный порт достаточно быстро, чтобы сразу открыть его снова. Из этого урока я узнал, что del действительно означало: "GC это сейчас! и подождите, пока это не будет сделано", и это действительно полезно во многих ситуациях. Конечно, у вас может быть system.gc.del_this_and_wait_balbalbalba(obj).

del является эквивалентом "unset" во многих языках и в качестве точки отсчета поперечного перемещения с другого языка программирования на Python.. люди склонны искать команды, которые делают то же самое, что они делали на своем первом языке... также установка дисп "" или ничего не снимают вар из сферы..оно просто опустошает его значение имя самого var по-прежнему будет храниться в памяти...зачем?!? в сценарии с интенсивной памятью..держать мусор за его просто нет и вообще...каждый язык там какой-либо "отключено" / "удалить" функция дисп..почему не питон?

каждый объект в python имеет идентификатор, тип, счетчик ссылок, связанный с ним, когда мы используем del счетчик ссылок уменьшается, когда счетчик ссылок становится нулевым, это потенциальный кандидат для сбора мусора. Это отличает del по сравнению с установкой идентификатора None. В более позднем случае это просто означает, что объект просто оставлен диким (пока мы не выйдем из области действия, и в этом случае количество будет уменьшено), и просто теперь идентификатор указывает на какой-то другой объект (ячейка памяти).