Cet article vous apporte des connaissances pertinentes sur Python, qui présente principalement des problèmes liés à CPython. Le garbage collector de CPython est la méthode intégrée de Python pour résoudre le problème de référence circulaire. J'espère que cela aidera tout le monde.
【Recommandation associée : Tutoriel vidéo Python3】
Le garbage collector de CPython (appelé GC) est la méthode intégrée de Python pour résoudre le problème de référence circulaire. Par défaut, il s'exécute toujours en arrière-plan et opère sa magie de temps en temps, vous n'avez donc pas à vous soucier des références circulaires qui encombrent votre mémoire.
Le garbage collector est conçu pour rechercher et supprimer des objets de référence circulaires de la mémoire de travail de CPython. Cela se fait de la manière suivante.
Détecter les objets référencés circulairement
Appeler la méthode finale __del__
qui supprime les pointeurs de chaque objet (afin de résoudre le problème de boucle), uniquement si la boucle est toujours orpheline après l'étape 2. Le
Une fois ce processus terminé, chaque objet qui était auparavant dans la boucle a désormais un nombre de références de 0, donc cet objet sera supprimé de la mémoire.
Bien qu'il fonctionne automatiquement, nous pouvons en fait l'importer en tant que module depuis la bibliothèque standard. Voici un exemple :
import gc
Le garbage collector de CPython garde la trace de divers objets qui existent en mémoire - mais pas de tous les objets. Nous pouvons instancier certains objets et voir si le garbage collector les récupérera.
>>> gc.is_tracked("a string") False >>> gc.is_tracked(["a", "list"]) True
Si un objet peut contenir des pointeurs, cela lui donne la capacité de faire partie d'une structure de référence circulaire - et c'est exactement pour cela que les détecteurs de déchets existent, pour les détecter et les démolir. En Python, ces objets sont souvent appelés « objets conteneurs ».
Ainsi, le ramasse-miettes doit connaître tous les objets qui peuvent exister dans le cadre d'une référence circulaire. Les chaînes ne le peuvent pas, donc "une chaîne" ne sera pas suivie par le ramasse-miettes. Les listes (comme nous l'avons vu) peuvent contenir des pointeurs, donc ['a', 'list'] est suivi.
Toutes les instances de classes définies par l'utilisateur seront également suivies par le ramasse-miettes puisque nous pouvons toujours leur définir des propriétés arbitraires (pointeurs).
>>> Wade = MyNameClass("Wade") >>> gc.is_tracked(Wade) True
Ainsi, le garbage collector connaît tous les objets pouvant former des références circulaires. Comment sait-il si une référence circulaire a été formée ?
Il connaît également tous les pointeurs de chaque objet et où ils pointent. Nous pouvons voir cette action.
>>> my_list = ["a", "list"] >>> gc.get_referents(my_list) ['list', 'a']
La méthode get_referents (également connue sous le nom de méthode traversal) reçoit un objet et renvoie une liste de pointeurs d'objet (ses références) qu'il contient. Ainsi, la liste ci-dessus contient des pointeurs vers chacun de ses éléments, qui sont des chaînes.
Regardons la méthode get_referents dans une boucle d'objets (bien qu'il ne s'agisse pas encore d'une référence circulaire, puisque les objets sont toujours accessibles depuis l'espace de noms).
>>> jane = MyNamedClass("Jane") >>> bob = MyNamedClass("Bob") >>> jane.friend = bob >>> bob.friend = jane >>> gc.get_referents(bob) [{'name': 'bob', 'friend': <__main__.MyNamedClass object at 0x7ff29a095d60>}, <class '__main__
Dans cette boucle, nous pouvons voir que l'objet pointé par bob contient des pointeurs vers : son dictionnaire de propriétés, contenant le nom de bob (bob) et ses amis (l'instance MyNamedClass également pointée par jane). L'objet bob possède également un pointeur vers l'objet de classe lui-même, puisque bob.class renverra cet objet de classe.
Lorsque le garbage collector s'exécute, il vérifie si chaque objet qu'il connaît (c'est-à-dire tout objet qui renvoie True lorsque vous appelez gc.is_tracked) est accessible depuis l'espace de noms. Pour ce faire, il garde une trace de tous les pointeurs de l'espace de noms, vers les pointeurs dans les objets vers lesquels ces pointeurs pointent, et ainsi de suite, jusqu'à ce qu'il ait construit une vue complète de tout ce qui est accessible à partir du code.
Si après cela, le GC constate que certains objets ne sont pas accessibles depuis l'espace de noms, il peut alors effacer ces objets.
N'oubliez pas que tous les objets encore en mémoire doivent avoir un nombre de références non nul, sinon ils seront supprimés en raison du nombre de références. Pour les objets inaccessibles mais ayant néanmoins un nombre de références non nul, ils doivent faire partie d'une référence circulaire, c'est pourquoi nous sommes si préoccupés par la possibilité que cela se produise.
Revenons à la boucle de référence, jane et bob, et transformons cette boucle en boucle isolée en supprimant le pointeur de l'espace de noms.
>>> del jane >>> del bob
Nous comprenons maintenant la situation exacte que le ramasse-miettes est censé résoudre. Nous pouvons déclencher le garbage collection manuel en appelant gc.collect().
>>> gc.collect() Deleting Bob! Deleting Jane! 4
Par défaut, le garbage collector effectuera automatiquement cette action de temps en temps (car de plus en plus d'objets sont créés et détruits pendant l'exécution de CPython).
Dans l'extrait de code ci-dessus, la sortie que nous voyons contient l'instruction print de la méthode __del__ de MyNamClass, avec un nombre à la fin - dans ce cas, 4. Ce nombre est généré par le garbage collector lui-même et nous indique combien d'objets ont été supprimés.
【Recommandations associées : Tutoriel vidéo Python3】
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!