Подтвердить что ты не робот

Способствует ли метод clear() слова удалить все объекты, связанные с объектом из памяти?

Если словарь содержит измененные объекты или объекты пользовательских классов (например, набор запросов или даже DateTime), то вызывает ли clear() в словаре удаление этих объектов из памяти? Ведет ли он себя иначе, чем цикл через dict и del для них?

например. Рассмотрим

class MyClass(object):
    '''Test Class.'''

my_obj_1 = MyClass()
my_obj_2 = MyClass()

my_dict = { 'foo' : my_obj_1, 'bar' : my_obj_2 }

то есть

my_dict.clear()

то же, что и

for key in my_dict.keys():
    del my_dict[key]

?

4b9b3361

Ответ 1

Документация на языке python сообщает, что del d[key] удаляет d[key] из словаря, а d.clear() удаляет каждый ключ, поэтому в основном их поведение то же самое.

В памяти проблема, в Python, когда вы "удаляете", вы в основном удаляете ссылку на объект. Когда объект не ссылается ни на какую переменную, ни на другой объект или не становится недоступным, он становится мусором и может быть удален из памяти. Python имеет сборщик мусора, который время от времени выполняет эту работу по проверке того, какие объекты являются мусором, и освобождает выделенную для них память. Если объект, который вы удаляете из словаря, ссылается на другую переменную, то он по-прежнему доступен, поэтому он не является мусором, поэтому он не будет удален. Я оставляю здесь некоторые ссылки, если вы заинтересованы в том, чтобы читать сборку мусора вообще и сборку мусора python в частности.

Ответ 2

Ведет ли он себя иначе, чем цикл через dict и del для них?

Здесь стоит отметить, что любой пользовательский класс, реализующий абстрактный базовый класс MutableMapping, получает clear() как "бесплатный" метод mixin.

Единственными методами, которые необходимо переопределить для создания подкласса MutableMapping, являются:

__getitem__, __setitem__, __delitem__, __iter__, __len__

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

import collections

class MyMap(collections.MutableMapping):
    def __init__(self, mydict):
        self._top_secret_data = mydict

    def __getitem__(self, key):
        print 'getitem'
        return self._top_secret_data[key]

    def __setitem__(self, key, value):
        raise Exception('where did you want that?')

    def __len__(self):
        raise Exception('a gentleman never tells')

    def __delitem__(self, key):
        print '[shredding intensifies]'
        del self._top_secret_data[key]

    def __iter__(self):
        def keygen():
            for key in self._top_secret_data:
                print 'faster! faster!'
                yield key
        return iter(keygen())

Используя класс, определенный выше, легко увидеть, как реализовано clear():

>>> m = MyMap({1:'a', 2:'b', 3:'c'})
>>> m.clear()
faster! faster!
getitem
[shredding intensifies]
faster! faster!
getitem
[shredding intensifies]
faster! faster!
getitem
[shredding intensifies]
>>> 

Другими словами, метод mixin clear() в основном реализуется как for key in self: del self[key].

Теперь отказ от ответственности: встроенные типы, такие как dict, реализованы на C, поэтому метод dict.clear может быть не идентичен буквам for key in mydict: del mydict[key]. Я бы ожидал некоторой оптимизации за кулисами, возможно, совершенно другой стратегии, но, надеюсь, этот пример дает вам некоторое представление о том, как можно ожидать, что метод clear() будет работать в Python.

Ответ 3

На самом деле существует очень маленькая разница между ними. clear() освободит память хэшета, используемого в dict, в то время как удаление ключа не будет.

a = dict.fromkeys(range(1000))

In [10]: sys.getsizeof(a)
Out[10]: 49432

In [11]: a.clear()

In [12]: sys.getsizeof(a)
Out[12]: 280

In [13]: a = dict.fromkeys(range(1000))

In [14]: for i in range(1000):
   ....:     del a[i]
   ....:     

In [15]: sys.getsizeof(a)
Out[15]: 49432

Ответ 4

Это то же самое, что и вызов del d['foo'] - он просто удаляет записи, но не влияет на сами ключи или значения.

Конечно, они могут стать сборщиками мусора, если нет других ссылок на них.

Ответ 5

В вашем случае два объекта MyClass являются общими. Они все равно будут доступны через my_obj_1 и my_obj_2.

Ответ 6

команда del удаляет ссылку на конкретный элемент в списке, команда clear очищает все пары значений ключа в ходу, поэтому функциональность такая же, как и для разыменования и отдыха, задача удаления из памяти выполняется мусором коллектор

Ответ 7

Вы даже пытались запустить код? Следующий код с Python 3.7 вызывает исключение! "RuntimeError: словарь изменил размер во время итерации":

for key in my_dict.keys():
    del my_dict[key]

Все предыдущие ответы хороши. Я просто хотел добавить еще пару моментов о различиях между del и clear:

  1. my_dict.clear(); удаляет все элементы в словаре и делает его эквивалентным пустому словарю. Примечание: вы все еще можете добавлять элементы к нему, если хотите!
  2. del my_dict; делает объект my_dict удаляемым и разрешает сборку мусора (my_dict больше не может использоваться)! Таким образом, если вы попытаетесь добавить/получить доступ к любому элементу, вы получите исключения.
  3. Кроме того, вы объявили две переменные my_obj_1 и my_obj_2; Даже если вы удалите/очистите my_dict, эти две переменные содержат ссылки на объекты MyClass и не исчезнут, пока my_obj_1 и my_obj_2 не выйдут из области видимости; Итак, если объекты MyClass содержат память (скажем, список или что-то в этом роде), то если вы намереваетесь освободить память, удалив/очистив my_dict, этого не произойдет!

    class MyClass (object): '' 'Тестовый класс.' ''

    my_obj_1 = MyClass() my_obj_2 = MyClass()