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

Должен ли я беспокоиться о круговых ссылках на Python?

Предположим, что у меня есть код, который поддерживает структуру родителя/ребенка. В такой структуре я получаю круговые ссылки, где ребенок указывает на родителя, а родитель указывает на ребенка. Должен ли я беспокоиться о них? Я использую Python 2.5.

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

4b9b3361

Ответ 1

"Беспокойство" неуместно, но если ваша программа оказывается медленной, потребляет больше памяти, чем ожидалось, или имеет странные необъяснимые паузы, причина, скорее всего, будет в этих циклах обработки мусора - им нужно быть мусором собранных по другой процедуре, чем "нормальные" (ациклические) эталонные графы, и эта коллекция является случайной и может быть медленной, если у вас много объектов, связанных в таких циклах (коллекция циклических мусора также запрещена, если объект в цикл имеет специальный метод __del__).

Таким образом, циклы ссылок не повлияют на правильность вашей программы, но могут повлиять на ее производительность и/или площадь.

Если и когда вы хотите удалить ненужные циклы ссылок, вы можете часто использовать модуль weakref в стандартной библиотеке Python.

Если и когда вы хотите использовать более прямой контроль (или выполнить отладку, посмотрите, что именно происходит) в отношении циклической сборки мусора, используйте gc в стандартной библиотеке Python.

Ответ 2

Экспериментально: вы в порядке:

import itertools

for i in itertools.count():
    a = {}
    b = {"a":a}
    a["b"] = b

Он постоянно остается при использовании 3,6 Мб ОЗУ.

Ответ 3

Python обнаружит цикл и освободит память, если нет внешних ссылок.

Ответ 4

Циркулярные ссылки - это нормальная вещь, поэтому я не вижу причины беспокоиться о них. Многие алгоритмы дерева требуют, чтобы каждый node имел ссылки на своих дочерних элементов и родителя. Они также должны реализовать что-то вроде двусвязного списка.

Ответ 5

Я не думаю, что тебе следует беспокоиться. Попробуйте следующую программу, и вы увидите, что она не будет потреблять всю память:

while True:
    a=range(100)
    b=range(100)
    a.append(b)
    b.append(a)
    a.append(a)
    b.append(b)

Ответ 6

Кажется, что существует проблема со ссылками на методы в списках в переменной. Вот два примера. Первый не вызывает __del__. Второй со слабым реком подходит для __del__. Однако в этом более позднем случае проблема заключается в том, что вы не можете слабо ссылаться на методы: http://docs.python.org/2/library/weakref.html

import sys, weakref

class One():
    def __init__(self):
        self.counters = [ self.count ]
    def __del__(self):
        print("__del__ called")
    def count(self):
        print(sys.getrefcount(self))


sys.getrefcount(One)
one = One()
sys.getrefcount(One)
del one
sys.getrefcount(One)


class Two():
    def __init__(self):
        self.counters = [ weakref.ref(self.count) ]
    def __del__(self):
        print("__del__ called")
    def count(self):
        print(sys.getrefcount(self))


sys.getrefcount(Two)
two = Two()
sys.getrefcount(Two)
del two
sys.getrefcount(Two)