Как немедленно освободить используемую память в списке python?
во многих случаях вы уверены, что определенно не будете использовать список снова, я надеюсь, что память должна быть выпущена прямо сейчас
a = [11,22,34,567,9999]
del a
Я не уверен, действительно ли он освобождает память, вы можете использовать
del a[:]
которые фактически удаляют все элементы в списке a.
так лучший способ его освободить?
def realse_list(a):
del a[:]
del a
не совсем уверен. Вы высказали свое мнение.
btw, как насчет кортежа и набора?
Ответы
Ответ 1
def release_list(a):
del a[:]
del a
Никогда не делай этого. Python автоматически освобождает все объекты, на которые не ссылаются больше, поэтому простой del a
гарантирует, что память списка будет выпущена, если в списке больше нет ссылок. В этом случае отдельные элементы списка также будут освобождены (и любые объекты, на которые ссылаются только они, и т.д. И т.д.), Если только некоторые из отдельных элементов также не упоминаются.
Это означает, что только время, когда del a[:]; del a
будет выпускать больше, чем del a
самостоятельно, это когда список ссылается где-то в другом месте. Это точно, когда вы не должны выгружать список: кто-то еще его использует!!!
В принципе, вы не должны думать об управлении фрагментами памяти. Вместо этого подумайте об управлении ссылками на объекты. В 99% всего кода Python Python очищает все, что вам не нужно, довольно скоро после того, как в последний раз вам это нужно, и проблем нет. Каждый раз, когда функция заканчивает все локальные переменные в этой функции "die", и если они указывают на объекты, которые не упоминаются нигде, они будут удалены, и это будет каскадироваться ко всему, что содержится в этих объектах.
Единственный раз, когда вам нужно подумать об этом, - когда у вас есть большой объект (скажем, огромный список), вы что-то делаете с ним, а затем начинаете длительный (или интенсивный) подсчет вычислений, где для суб-вычисления не требуется большой объект. Поскольку у вас есть ссылка на него, большой объект не будет выпущен до тех пор, пока суб-вычисление не закончится, а затем вы вернетесь. В таком случае (и только в этом случае) вы можете явно del
ссылаться на большой объект перед тем, как приступить к суб-вычислению, так что большой объект может быть освобожден раньше (если никто не используя его, если вызывающий объект передал вам объект, а вызывающий сделал все еще нуждался в нем после того, как вы вернетесь, вы будете очень рады, что он не будет выпущен).
Ответ 2
Как отмечает @monkut, вы, вероятно, не должны слишком беспокоиться об управлении памятью в большинстве ситуаций. Если у вас есть гигантский список, с которым вы уверены, что с ним все закончилось, и он не выйдет из текущей области действия на некоторое время:
del a
просто удаляет ваше имя a
для этого фрагмента памяти. Если какая-либо другая функция или структура или что-то еще ссылается на нее, она не будет удалена; если этот код имеет единственную ссылку на этот список под именем a
, и вы используете CPython, эталонный счетчик немедленно освободит эту память. Другие реализации (PyPy, Jython, IronPython) могут не убить его сразу, потому что у них разные сборщики мусора.
Из-за этого оператор del a
в вашей функции realse_list
фактически ничего не делает, потому что у вызывающего все еще есть ссылка!
del a[:]
будет, как вы заметили, удалить элементы из списка и, следовательно, большую часть использования памяти.
Вы можете сделать the_set.clear()
для аналогичного поведения с наборами.
Все, что вы можете сделать с кортежем, потому что они неизменяемы, del the_tuple
и надеюсь, что никто другой не ссылается на него, но вы, вероятно, не должны иметь огромные кортежи!
Ответ 3
Python использует количество ссылок для управления своим ресурсом.
import sys
class foo:
pass
b = foo()
a = [b, 1]
sys.getrefcount(b) # gives 3
sys.getrefcount(a) # gives 2
a = None # delete the list
sys.getrefcount(b) # gives 2
В приведенном выше примере счетчик ссылок будет увеличен при добавлении его в список, и, как вы можете видеть, при удалении списка счетчик ссылок b также уменьшается. Итак, в вашем коде
def release_list(a):
del a[:]
del a
был избыточным.
В общем, все, что вам нужно сделать, это присвоить список объекту None или использовать ключевое слово del, чтобы удалить список из словаря атрибутов. (a.k.a, чтобы отвязать имя от фактического объекта). Например,
a = None # or
del a
Когда счетчик ссылок объекта обращается в нуль, python освободит память для вас. Чтобы убедиться, что объект удален, вы должны убедиться, что никакие другие места не ссылаются на объект по имени или по контейнеру.
sys.getrefcount(b) # gives 2
Если sys.getrefcount дает вам 2, это означает, что вы единственный, у кого была ссылка на объект и когда вы делаете
b = None
он освободится из памяти.
Ответ 4
Если вы беспокоитесь об управлении памятью и производительности для типов данных, почему бы не использовать что-то вроде связанной двойной очереди.
Сначала его память отстает от памяти, поэтому вам не придется выделять большой кусок непрерывной памяти сразу с места в карьер.
Во-вторых, вы увидите более быстрое время доступа для enqueueing и dequeueing, потому что, в отличие от стандартного списка, когда вы удаляете, можно сказать, что средний элемент не нужен для сдвига остальной части списка в индексе, который занимает много времени в больших списках.
Я также должен отметить, что если вы используете только целые числа, я бы предложил посмотреть в двоичную кучу, поскольку вы увидите время доступа O (log ^ 2n) по сравнению с главным образом O (N) со списками.