Когда-дель-полезное в Python?
Я не могу действительно думать о какой-либо причине, почему python нуждается в del ключевое слово (и большинство языков, кажется, нет подобного сайта). Например, вместо удаления переменной можно просто назначить None к нему. А при удалении из словаря, a del метод может быть добавлен.
есть ли причина, чтобы держать del в python, или это остаток дней предварительной сборки мусора Python?
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. В более позднем случае это просто означает, что объект просто оставлен диким (пока мы не выйдем из области действия, и в этом случае количество будет уменьшено), и просто теперь идентификатор указывает на какой-то другой объект (ячейка памяти).