J'ai la fonction suivante:
def myfn():
big_obj = BigObj()
result = consume(big_obj)
return result
Quand le nombre de références est-il pour la valeur de Bigobj () augmenté/diminué: est-ce:
consume(big_obj)
est appelé (puisque BIG_OBJ n'est pas référencé par la suite dans MYFN)Cela ferait-il une différence pour changer la dernière ligne pour:
return consume(big_obj)
Modifier (Clarification des commentaires):
Mais qu'avez-vous avec les temporaires (E.G F1 (F2 ())?
J'ai vérifié des références aux temporaires avec ce code:
import sys
def f2(c):
print("f2: References to c", sys.getrefcount(c))
def f0():
print("f0")
f2(object())
def f1():
c = object()
print("f1: References to c", sys.getrefcount(c))
f2(c)
f0()
f1()
Ceci imprime:
f0
f2: References to c 3
f1: References to c 2
f2: References to c 4
Il semble que les références à des variables temporaires ont lieu. Ce n'est pas que Getrefcount en donne une plus que vous ne vous attendez pas parce que cela tient une référence aussi.
Disclaimer: La plupart des informations proviennent des commentaires. Alors crédit pour tout le monde qui a participé à la discussion.
Lorsqu'un objet est supprimé est un détail de mise en œuvre en général. Je vais me référer à CPHON, qui est basé sur le comptage de référence. J'ai exécuté les exemples de code avec CPPHON 3.10.0.
Le dernier point est même valable pour des références temporaires telles que f(g())
. La dernière référence à g() est supprimée, lorsque F retourne (en supposant que g n'enregistre pas une référence quelque part) voir ici
Donc, pour l'exemple de la question:
def myfn():
big_obj = BigObj() # reference 1
result = consume(big_obj) # reference 2 on the stack frame for
# consume. Not yet counting any
# reference inside of consume
# after consume returns: The stack frame
# and reference 2 are deleted. Reference
# 1 remains
return result # myfn returns reference 1 is deleted.
# BigObj is deleted
def consume(big_obj):
pass # consume is holding reference 3
Si nous changerions cela pour:
def myfn():
return consume(BigObj()) # reference is still saved on the stack
# frame and will be only deleted after
# consume returns
def consume(big_obj):
pass # consume is holding reference 2
Comment puis-je vérifier de manière fiable, si un objet a été supprimé?
Vous ne pouvez pas compter sur gc.get_Objects (). GC est utilisé pour détecter et recycler les cycles de référence. Chaque référence n'est pas suivie par le GC. Vous pouvez créer une référence faible et vérifiez si la référence est toujours valide.
class BigObj:
pass
import weakref
ref = None
def make_ref(obj):
global ref
ref = weakref.ref(obj)
return obj
def myfn():
return consume(make_ref(BigObj()))
def consume(obj):
obj = None # remove to see impact on ref count
print(sys.getrefcount(ref()))
print(ref()) # There is still a valid reference. It is the one from consume stack frame
myfn ()
Comment transmettre une référence à une fonction et supprimer toutes les références de la fonction d'appel?
Vous pouvez encadrer la référence, passer à la fonction et effacer la référence en boîte de l'intérieur de la fonction:
class Ref:
def __init__(ref):
self.ref = ref
def clear():
self.ref = None
def f1(ref):
r = ref.ref
ref.clear()
def f2():
f1(Ref(object())