¿Debo preocuparme por las referencias circulares en Python?

Supongamos que tengo un código que mantiene una estructura padre / hijo. En tal estructura, obtengo referencias circulares, donde un niño señala a un padre y un padre señala a un niño. ¿Debo preocuparme por ellos? Estoy usando Python 2.5.

Me preocupa que no se recolecten los residuos y que la aplicación consumirá toda la memoria.

La “preocupación” está fuera de lugar, pero si su progtwig resulta lento, consume más memoria de lo esperado o tiene pausas extrañas e inexplicables, es probable que la causa esté en esos bucles de referencia de basura: deben ser recolectados por un procedimiento diferente al de los gráficos de referencia “normales” (acíclicos), y esa recolección es ocasional y puede ser lenta si tiene muchos objetos vinculados en dichos bucles (la recolección de basura cíclica también se inhibe si un objeto en el bucle tiene una __del__ método especial).

Por lo tanto, los bucles de referencia no afectarán la corrección de su progtwig, pero pueden afectar su rendimiento y / o huella.

Si y cuando desea eliminar bucles no deseados de referencias, a menudo puede usar el módulo weakref en la biblioteca estándar de Python.

Si y cuando desea ejercer un control más directo (o realizar una depuración, vea qué está sucediendo exactamente) con respecto a la recolección de basura cíclica, use el módulo gc en la biblioteca estándar de Python.

Experimentalmente: estás bien:

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

Se mantiene constantemente en el uso de 3,6 MB de RAM.

Python detectará el ciclo y liberará la memoria cuando no haya referencias externas.

Las referencias circulares son una cosa normal, por lo que no veo una razón para preocuparme por ellas. Muchos algoritmos de árbol requieren que cada nodo tenga enlaces a sus hijos y su padre. También se les exige que implementen algo como una lista doblemente enlazada.

No creo que debas preocuparte. Pruebe el siguiente progtwig y verá que no consumirá toda la memoria:

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

Parece que hay un problema con las referencias a los métodos en las listas en una variable. Aquí hay dos ejemplos. El primero no llama a __del__ . El segundo con weakref está bien para __del__ . Sin embargo, en este último caso, el problema es que no puede hacer referencia débilmente a los métodos: 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)