Когда-дель-полезное в 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. В более позднем случае это просто означает, что объект просто оставлен диким (пока мы не выйдем из области действия, и в этом случае количество будет уменьшено), и просто теперь идентификатор указывает на какой-то другой объект (ячейка памяти).