python - estructura - modelo transitorio odoo
¿Cadenas no referenciadas por los dicts? (1)
De gcmodule.c
:
Ciertos tipos de contenedores no pueden participar en un ciclo de referencia, por lo que no necesitan ser rastreados por el recolector de basura. La eliminación de estos objetos reduce el costo de las recolecciones de basura. Sin embargo, determinar qué objetos no se rastrear no es gratuito, y los costos deben sopesarse con los beneficios de la recolección de basura.
...
Los diccionarios que contienen solo objetos inmutables tampoco necesitan ser rastreados. Los diccionarios no se rastrean cuando se crean. Si un elemento rastreado se inserta en un diccionario (ya sea como una clave o valor), el diccionario queda rastreado. Durante una recolección completa de basura (todas las generaciones), el recopilador deshará los diccionarios cuyo contenido no se rastrea.
Básicamente, dado que los objetos en Python son de referencia, el objetivo del recolector de basura es romper los ciclos de referencia, otros objetos sin referencia se destruyen cuando desaparece la última referencia. Para la optimización, el recolector de basura no realiza un seguimiento de ciertos objetos que simplemente no pueden participar en los ciclos de referencia.
Entonces, se hace referencia a las cadenas. Sin embargo, el recolector de basura no está interesado en absoluto en estos diccionarios y, por gc.get_referrers()
tanto, gc.get_referrers()
no los incluye.
Mira este código de Python:
from gc import get_referrers as refs
x = ''x''
d = {x:x}
print(d in refs(x))
Imprime falso. Eso es extraño por sí mismo, pero se vuelve mucho más extraño cuando se considera lo siguiente:
Si x es un número (int, float, complex, Fraction, Decimal) en lugar de una cadena, sigue imprimiendo False. Para bytes y bytearray, también. Pero para cualquier otro tipo (hashable si se usa como clave, como tuple o frozenset, pero muchos otros, si se usa solo como valor), se imprime True.
Si d es cualquier otro contenedor (conjunto, lista, tupla ...) que contenga x, imprime True. Solo para un dict, imprime False. Además, no importa si x es una clave o un valor, o como arriba, ambos.
Pensé en Python que cada objeto es una referencia (a diferencia de Java, que tiene tipos primitivos, o Ruby, que tipos de valor pequeños), pero ahora parece que str e int son tipos algo primitivos, que no están referenciados. Pero, por otro lado, ¿por qué solo en los dicts?
También sé que las entradas de -5 a 256 se almacenan en caché en CPython (y se pueden intercalar cadenas pequeñas), por lo que tiene sentido no volver a contarlas, ya que nunca se eliminarán de todos modos, pero esto funciona para cualquier número entero (y cadenas largas ) Lo he intentado, mucho más grande que ese rango.
¿Alguien sabe lo que está pasando aquí?
--- ACTUALIZACIÓN ---
Más curioso y curioso ... parece que las clases datetime {datetime, date, time} tienen el mismo comportamiento "sin referencias". Ahora, sé algo que esos, AnyStr y Number tienen en común: sus hash se aleatorizan con una sal por sesión. Pero esto no tiene ningún sentido, ya que el comportamiento se observa incluso cuando estos son meramente valores en dicts, no en keys. Y los valores no son hash. ¿O son?