Python Delegate Pattern - Comment éviter les références circulaires?


0 Answers

Pourquoi ne serait-il pas ramassé à la fin? Lorsque le script est terminé et que python termine l'exécution, toute la section de la mémoire sera marquée pour la récupération de place et (éventuellement) la récupération du système d'exploitation.

Si vous exécutez ceci dans un programme de longue durée, une fois que A et B sont tous deux déréférencés, alors la mémoire sera récupérée.

Question

Je voudrais demander si l'utilisation du pattern Delegate en Python conduirait à des références circulaires et si oui, quelle serait la meilleure façon de l'implémenter pour s'assurer que l'objet et son délégué seront récupérés?

En Objective C, le problème ci-dessus est évité en utilisant une référence faible au délégué. En C ++, nous n'appelons pas delete sur le délégué. J'ai trouvé un lien vers le module de référence faible de Python ici: http://docs.python.org/library/weakref.html . Il semble qu'une approche plausible pourrait être de créer une référence faible pour faire référence à la variable d'instance en utilisant ce module, mais je ne suis pas sûr.

Comme j'ai tapé cette question sur google et que je n'ai pas trouvé de réponses, je me demande si c'est un problème en Python ou s'il y a une solution commune (sans le module weakref) que je ne connais pas de? En outre, j'ai fait une recherche sur avant de le demander, mais les questions que j'ai trouvées traitent soit des importations circulaires, soit du modèle de délégué en général et non spécifique à Python et du problème des références circulaires.

Merci d'avance pour toute réponse.

Ci-dessous est un code pour un exemple de jouet pour aider à illustrer ma question. J'ai implémenté le code de cette manière et cela fonctionne mais je ne suis pas sûr que la mémoire soit récupérée à la fin.

class A(object):
    def __init__(self):
        self.delegate = None

        # Some other instance variables that keep track of state for performing some tasks.

    def doSomething(self):
        if self.delegate is not None:
            self.delegate.doSomething()
        else:
            print('Cannot perform task because delegate is not set.')

    # Other methods not shown.

class B(object):
    def __init__(self):
        self.a = A() # Need to keep object 'a' from garbage collected so as to preserve its state information.
        self.a.delegate = self  # Is this a circular reference? How to 'fix' it so that A and B will eventually be garbage collected?

    def doSomething(self):
        print('B doing something')

    # Other methods not shown.

EDITER :

Après avoir lu certaines des réponses, j'ai décidé de clarifier ma question. Je comprends que Python a garbage collection. Ce dont je n'étais pas sûr, c'était s'il allait effectuer la récupération de place sur les objets référencés circulaires. Mes soucis proviennent du passage suivant du document de Python:

Détail de l'implémentation de CPython: CPython utilise actuellement un schéma de comptage avec détection retardée (facultative) de la corruption cyclique, qui collecte la plupart des objets dès qu'ils deviennent inaccessibles, mais n'est pas garanti de collecter les déchets contenant des références circulaires . Voir la documentation du module gc pour plus d'informations sur le contrôle de la collecte des déchets cycliques. D'autres implémentations agissent différemment et CPython peut changer. Ne dépendez pas de la finalisation immédiate des objets lorsqu'ils deviennent inaccessibles (ex: toujours fermer les fichiers).

Le passage dans sa forme originale peut être trouvé ici: http://docs.python.org/reference/datamodel.html Le paramètre gras est le mien.

Le message suivant fournit une explication plus claire sur le problème des objets référencés circulaires et pourquoi il empêcherait la récupération de place sur ces objets (au moins dans un environnement typique): http://www.electricmonk.nl/log/2008/07/07 / python-destructor-et-garbage-collection-notes / .

De plus, je viens de rencontrer la réponse d'Alex Martellli à la question suivante: les utilisateurs de Python devraient-ils s'inquiéter de la référence circulaire: Devrais-je m'inquiéter des références circulaires dans Python? De sa réponse, je comprends que même si les objets référencés circulaires finiront par être ramassés, MAIS il y aurait des frais généraux. Que cela soit significatif dépend du programme.

De plus, il a mentionné utiliser le module weakref de Python mais n'a pas explicitement dit comment.

Par conséquent, je voudrais ajouter les questions suivantes pour clarifier certaines questions non résolues:

  1. Les docs disent que la collection garbaged n'est pas garantie pour les objets référencés circulaires. Mais d'après les réponses, il semble que ce ne soit pas le cas. Ai-je mal compris le passage ou y a-t-il d'autres détails que j'ai manqués?
  2. Je suppose que l'utilisation d'une référence faible, comme indiqué dans la réponse d'Alex et ma question, permettrait d'éviter complètement les frais généraux du problème?

Encore merci pour les réponses.




Related