84 votes

Qu'est-ce que __weakref__ en Python?

Étonnamment, il n'y a pas de documentation explicite pour __weakref__. Références faibles sont expliquées ici. __weakref__ est également peu mentionné dans la documentation de l' __slots__. Mais je ne pouvais pas trouver quelque chose à propos de __weakref__ lui-même.

Qu'est-ce exactement est - __weakref__? - Est-ce juste un membre qui agit comme un drapeau: le Cas échéant, l'objet peut être mal référencé? - Ou est-ce une fonction/variable qui peut être remplacée/attribué à obtenir un comportement souhaité? Comment?

69voto

Dunes Points 6740

__weakref__ est juste un objet opaque que les références toutes les références faibles à l'objet en cours. En réalité, il est une instance de weakref (ou, parfois, weakproxy) qui est à la fois une faible référence à l'objet qui fait partie d'une liste doublement liée à toutes les références faibles pour cet objet.

C'est juste un détail d'implémentation qui permet le garbage collector pour informer les références faibles qu'il est référent a été recueilli, et de ne pas autoriser l'accès à ce sous-jacent de pointeur.

La faiblesse de référence ne peut pas compter sur la vérification de la valeur de référence de l'objet auquel il se réfère. C'est parce que la mémoire peut avoir été récupérée et maintenant utilisé par un autre objet. Meilleur des cas, la machine virtuelle va se planter, dans le pire des cas, la faiblesse de référence permettra l'accès à un objet, qu'il n'était pas à l'origine référence. C'est pourquoi le garbage collector doit informer la référence faible, il est le référent n'est plus valide.

Voir weakrefobject.h pour la structure et la C-API pour cet objet. Et la mise en œuvre du détail est ici

49voto

dhke Points 2923

[Edit 1: Expliquer la liste liée à la nature et quand weakrefs sont réutilisés]

Curieusement, la documentation officielle est quelque peu non éclairant sur ce sujet:

Sans un __weakref__ variable pour chaque exemple, les classes définissant __slots__ ne prennent pas en charge la faiblesse des références à ses instances. Si la faiblesse de support de référence est nécessaire, puis ajouter __weakref__ à la séquence de chaînes dans l' __slots__ déclaration.

L' type objet de la documentation sur le sujet ne semble pas aider les choses trop:

Quand un type __slots__ déclaration contient un slot nommé __weakref__, ce logement devient la faiblesse de la tête de liste de référence pour les instances de type et l'emplacement de l'offset est stocké dans le type de l' tp_weaklistoffset.

Références faibles forme d'une liste chaînée. À la tête de cette liste (la première faiblesse de la référence à un objet) est disponible via __weakref__. Weakrefs sont ré-utilisés chaque fois que possible, de sorte que la liste (pas une liste Python!) généralement est vide ou ne contient qu'un seul élément.

Exemple:

Lors de la première utilisation weakref.ref(), vous créez une nouvelle faiblesse de la chaîne de référence pour l'objet cible. La tête de cette chaîne est le nouveau weakref et est stocké dans l'objet cible de l' __weakref__:

>>> import weakref
>>> class A(object): pass
>>> a = A()
>>> b = weakref.ref(a)
>>> c = weakref.ref(b)
>>> print(b is c is a.__weakref__)
True

Comme nous pouvons le voir, b re-utilisé. Nous pouvons force python pour créer un nouveau weakref, par exemple par l'ajout d'un paramètre de rappel:

>>> def callback():
>>>   pass
>>> a = A()
>>> b = weakref.ref(a)
>>> c = weakref.ref(b, callback)
>>> print(b is c is a.__weakref__)
False

Maintenant, b is a.__weakref__, et c est la deuxième référence de la chaîne. La chaîne de référence n'est pas directement accessible à partir du code Python. Nous ne voyons que l'élément de tête de la chaîne (b), mais pas de la façon dont la chaîne continue (b -> c).

Donc, __weakref__ est à la tête de l'interne lié liste de toutes les références faibles à l'objet. Je ne peux pas trouver n'importe quelle pièce de la documentation officielle où ce rôle de __weakref__ est, de façon concise, a expliqué, donc on ne devrait probablement pas compter sur ce comportement, comme c'est un détail d'implémentation.

22voto

Kasramvd Points 32864

L' __weakref__ variable est un attribut qui fait l'objet de soutenir les références faibles et la préservation de la faiblesse des références à l'objet.

La documentation python a expliqué de la manière suivante:

quand il ne reste références à un référent sont des références faibles, la collecte des ordures est libre de détruire le référent et la réutilisation de la mémoire de quelque chose d'autre.

Par conséquent, le devoir de la faiblesse des références est de fournir les conditions d'un objet afin d'être en mesure d'être des ordures collectées indépendamment de son type et de l'étendue.

Et à propos de l' __slots__, on peut d'abord regarder dans la documentation qui l'explique très bien:

Par défaut, les instances de classes ont un dictionnaire pour le stockage des attributs. Cela gaspille de l'espace pour les objets ayant très peu de variables d'instance. La consommation de l'espace peut devenir aiguë lors de la création d'un grand nombre de cas.

La valeur par défaut peut être remplacée par la définition d' __slots__ dans une définition de classe. L' __slots__ déclaration prend une séquence de variables d'instance et les réserves de juste assez d'espace dans chaque cas pour contenir une valeur pour chaque variable. L'espace est sauvé parce qu' __dict__ n'est pas créé pour chaque instance.

Maintenant, puisque, en utilisant __slots__ vous aurez le contrôle de l'demandé de stockage et d'un attribut, il empêche la création automatique d' __dict__ et __weakref__ pour chaque instance. Qui l' __weakref__ est la variable de chaque objet afin d'être en mesure de traiter avec les références faibles.

Aussi, en plus de tous ces la documentation pour object.__slots__ de la classe dit:

Cette variable de classe peut être affecté à une chaîne, itératif, ou d'une séquence de chaînes de caractères avec des noms de variables utilisés par les instances. __slots__ réserve de l'espace pour les variables déclarées et empêche la création automatique d' __dict__ et __weakref__ pour chaque instance.

Donc, En résumé, nous pouvons conclure que __slots__ sont de la gestion de l'allocation de stockage manuellement et depuis __weakref__ est la licence de l'acceptation de la faiblesse des références pour les objets qui sont liés au stockage (en raison de la capacité de déchets de la collecte), par conséquent __slots__ contrôle l' __weakref__ ainsi que le contrôle de l' __dict__ attribut.

La documentation vous a montré la voie de la réalisation d'un objet à l'appui de la faiblesse de références tout au long de l'aide d' __slots__:

Sans un __weakref__ variable pour chaque exemple, les classes définissant __slots__ ne prennent pas en charge la faiblesse des références à ses instances. Si la faiblesse de support de référence est nécessaire, puis ajouter '__weakref__' à la séquence de chaînes dans l' __slots__ déclaration.

Voici un exemple en python 3.X:

>>> class Test:
...     __slots__ = ['a', 'b']
... 
>>> 
>>> import weakref
>>> 
>>> t = Test()
>>> 
>>> r = weakref.ref(t)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot create weak reference to 'Test' object
>>> 
>>> class Test:
...     __slots__ = ['a', 'b', '__weakref__']
... 
>>> t = Test()
>>> r = weakref.ref(t)
>>> 
>>> t.__weakref__
<weakref at 0x7f735bc55d68; to 'Test' at 0x7f735bc51fc8>

Mais en python 2.7, bien que la documentation est comme susmentionnés, de docs, de la création d'une référence faible à partir d'instances qui ne fournit pas l' __weakref__ variable dans leur __slots__ noms ne soulève pas un TypeError:

>>> class Test:
...    __slots__ = ['a', 'b']
... 
>>> t = Test()
>>> 
>>> r = weakref.ref(t)
>>> 
>>> r
<weakref at 0x7fe49f4185d0; to 'instance' at 0x7fe4a3e75f80>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X