IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Liste des instances d'une classe


Sujet :

Python

  1. #21
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 790
    Par défaut
    Salut,

    Le proxy pour les weakref, faudrait m'expliquer, j'ai rien compris.
    Pour accéder à l'instance à partir du ref, il faut faire ref() et construire la liste des instances à partir de la liste des ref. Le proxy retourne un objet qui évite cette jonglerie.

    Je préfère utiliser le callback car il évite d'avoir à stocker le _ref ou le _proxy dans l'objet (mais le callback est lui stocké par weakref, donc çà n'économise par la mémoire du système juste la mienne .

    Fondamentalement, je suis d'accord avec l'approche de PauseKawa: un "truc" externe à la classe qui gère un dict (cls, instances).
    => Le callback devrait être dans "truc" et recevoir cls, ref en paramètres.

    La complication est qu'à partir du moment où on prend le couteau pour décider ce qui reste sous la responsabilité de Toto et ce qui va sous la responsabilité de "Truc"...
    çà "discustaille" côté création (héritage, metaclass,...) mais le callback permet de fermer le sujet côté destruction.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  2. #22
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Bonjour,

    j'ai pensé à implémenter une classe WeakList pour simplifier un peu les choses; il y a déjà un WeakSet et deux WeakDictionaries dans le module weakref, mais pas de WeakList.

    Mais je rencontre (en Python 2.7) un problème que je ne comprends pas.
    Voici un code minimal qui montre le problème.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    import weakref
     
    class WeakList(list):
     
        def append(self, val):
            list.append(self, weakref.proxy(val, self.remove))
     
    class Toto(object):
        instances = WeakList()
     
        def __init__(self):
            self.instances.append(self)
     
    t1 = Toto()
    t2 = Toto()
    print Toto.instances
    del t1
    print Toto.instances
    t3 = Toto()
    print Toto.instances
    del t3
    print Toto.instances
    Et le résultat que j'obtiens:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    [<weakproxy at 02808270 to Toto at 027E7F90>, <weakproxy at 02808990 to Toto at 02812170>]
    [<weakproxy at 02808990 to Toto at 02812170>]
    [<weakproxy at 02808990 to Toto at 02812170>, <weakproxy at 02808270 to Toto at 027E7F90>]
    Exception ReferenceError: 'weakly-referenced object no longer exists' in <built-in method remove of WeakList object at 0x028089C0> ignored
    [<weakproxy at 02808990 to Toto at 02812170>, <weakproxy at 02808270 to NoneType at 1E1EA16C>]
    Au début tout se passe bien, mais parfois (ici, à la ligne del t3) il semblerait que le callback soit appelé après que l'objet ait été libéré. Quel intérêt d'avoir un callback si on n'est pas certain qu'il soit exécuté quand il faut ? Et quand bien même, ce ne serait pas si grave pour ce cas d'utilisation, s'il se contentait de supprimer la référence invalide au lieu de lever une exception qui annule le remove.

    Cela n'a pas l'air de se produire si j'utilise weakref.ref au lieu de weakef.proxy. Cela permet de contourner le problème, mais c'est tout de même dommage que le callback ne soit pas appelé quand il faut...
    Si quelqu'un peut m'éclairer, je lui en serais reconnaissant.

  3. #23
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 790
    Par défaut
    Bonjour Dividee,

    Merci pour ce joli exemple.

    Au début tout se passe bien, mais parfois (ici, à la ligne del t3) il semblerait que le callback soit appelé après que l'objet ait été libéré.
    Sur mon bousin Windows7, le problème est systématique que ce soit sous Python 2.7 ou Python 3.2 *MAIS* semble dépendre de l'ordre des del: si je fais del t2 à la place de del t3, pas de "Exception ReferenceError:"

    De plus, la doc disant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Note
     
    Weak references to an object are cleared before the object’s __del__() is called, to ensure that the weak reference callback (if any) finds the object still alive
    J'appellerai cela un bug... mais que j'utilise .ref ou .proxy lorsque j'essaie d'accéder à l'objet associé (print) dans le cas .ref çà sort None et dans le cas .proxy çà lève l'exception.

    Outre que ce ne soit pas le sens que je donne à : "to ensure that the weak reference callback (if any) finds the object still alive"... pourquoi lorsqu'on utilise des .proxy, le comportement dépend de l'ordre des del....

    Par contre, dans les deux cas, le callback est appelé avant __del__ (lorsqu'on sort de l'interpréteur, le callback n'est pas appelé, mais c'est raisonnable).

    Je ne sais trop qu'en penser.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  4. #24
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonjour,

    Je suis surpris des réactions sous Seven pour ce qui est du callback. Pour moi il est exécuté dans tous les cas.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    import weakref
    from sys import version
     
    if version.startswith('3'):
        raw_input = input
     
    class WeakList(list):
     
        def append(self, val):
            list.append(self, weakref.proxy(val, self.on_delete))
     
        def on_delete(self, val):
            print('>>> pass on_delete')
            _tmplist = [_item for _item in self.__iter__() if dir(_item) != []]
            del self[:]
            for _item in _tmplist:
                list.append(self, _item)
     
     
    class Toto(object):
        instances = WeakList()
     
        def __init__(self):
            self.instances.append(self)
     
    t1 = Toto()
    t2 = Toto()
    print('proxy >>>', Toto.instances)
    del t2
    print('proxy >>>', Toto.instances)
    t3 = Toto()
    t4 = Toto()
    del t3
    print('proxy >>>', t4.instances)
    del t1
    print('proxy >>>', t4.instances)
    raw_input('fin\n')
    Output
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    proxy >>> [<weakproxy at 0xb748f07c to Toto at 0xb748accc>, <weakproxy at 0xb748f0a4 to Toto at 0xb748acec>]
    >>> pass on_delete
    proxy >>> [<weakproxy at 0xb748f07c to Toto at 0xb748accc>]
    >>> pass on_delete
    proxy >>> [<weakproxy at 0xb748f07c to Toto at 0xb748accc>, <weakproxy at 0xb748f0f4 to Toto at 0xb748ad2c>]
    >>> pass on_delete
    proxy >>> [<weakproxy at 0xb748f0f4 to Toto at 0xb748ad2c>]
    fin
     
    >>> pass on_delete
    Le ReferenceError devrait être systématique dans le cadre d'un del de la référence. Le callback pouvant être une fonction de la référence il est nécessaire de lever une erreur dans le cadre du proxy avant d'aller plus loin ("to ensure that the weak reference callback (if any) finds the object still alive") car le proxy est un objet a part.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    >>> class Foo:
    ...     pass
    ... 
    >>> f = Foo()
    >>> p = weakref.proxy(f)
    >>> del f
    >>> p
    <weakproxy at 0xb75e11bc to NoneType at 0x826c758>
    >>> dir(p)
    []
    >>> del p
    bug or feature ?

    On pourrais avoir le code de test et ses outputs sous Windows 7 wiztricks ?

    @+

    Edit
    Pour moi ceci
    Citation Envoyé par PauseKawa Voir le message
    Le callback pouvant être une fonction de la référence il est nécessaire de lever une erreur dans le cadre du proxy avant d'aller plus loin ("to ensure that the weak reference callback (if any) finds the object still alive") car le proxy est un objet a part.
    explique cela
    Citation Envoyé par wiztricks Voir le message
    Par contre, dans les deux cas, le callback est appelé avant __del__ (lorsqu'on sort de l'interpréteur, le callback n'est pas appelé, mais c'est raisonnable)
    @++

  5. #25
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 790
    Par défaut
    Salut PauseKawa,

    Mon code est le même que le précédent auquel j'ai ajouté les créations/del de Dividee. Mon soucis n'est pas que çà appelle ou pas le callback mais l'état dans lequel est le weakref qu'il reçoit.

    Si on relit la documentation un peu plus loin, il est dit que:
    class weakref.ref(object[, callback])¶

    Return a weak reference to object. The original object can be retrieved by calling the reference object if the referent is still alive; if the referent is no longer alive, calling the reference object will cause None to be returned. If callback is provided and not None, and the returned weakref object is still alive, the callback will be called when the object is about to be finalized; the weak reference object will be passed as the only parameter to the callback; the referent will no longer be available.
    Comme pour le weakref.proxy c'est la même chose, l'état du weakref semble "normal".

    Plus sioux, c'est les accès au proxy que fait list.remove qui dans certains cas lèvent ou pas l'exception... Mais si nous acceptons que "the referent will no longer be available", pas étonnant que çà fonctionne "de temps en temps".

    Le PEP205 qui raconte un peu comment cela est fait dit:

    ... Operations on proxy objects after
    the referent dies cause weakref.ReferenceError to be raised in
    most cases. "is" comparisons, type(), and id() will continue to
    work, but always refer to the proxy and not the referent.

    The callbacks registered with weak references must accept a single
    parameter, which will be the weak reference or proxy object
    itself. The object cannot be accessed or resurrected in the
    callback.

    L'idée de la liste de weakref.proxy est peut être une bonne idée mais... s'appuyer sur le callback pour faire des remove, c'est très moyen et grand merci a Dividee d'avoir pointé le "bug".

    A défaut de pouvoir s'appuyer sur le callback, nous pouvons quand même faire cela dans le __del__:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    import weakref
     
    class Toto(object):
        instances = []
     
        def __init__(self, number):
            self.number = number
            self._px = weakref.proxy(self)
            self.instances.append(self._px)
     
        def __del__(self):
            print ('__del__(%s)' % self)
            self.instances.remove(self._px)
     
        def __str__(self):
            return 'Toto: number=%d' % self.number
     
    t1 = Toto(1)
    t2 = Toto(2)
    print (Toto.instances)
    del t1
    print (Toto.instances)
    t3 = Toto(3)
    print (Toto.instances)
    del t3
    print (Toto.instances)
     
    print ('done')

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  6. #26
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonsoir,

    J'ai du mal là...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    from sys import version
     
    if version.startswith('3'):
        raw_input = input
     
    import weakref
     
    class Toto(object):
        instances = []
     
        def __init__(self, number):
            self.number = number
            self._px = weakref.proxy(self)
            self.instances.append(self._px)
     
        def __del__(self):
            print ('__del__(%s)' % self)
            self.instances.remove(self._px)
     
        def __str__(self):
            return 'Toto: number=%d' % self.number
     
    t1 = Toto(1)
    t2 = Toto(2)
    print (Toto.instances)
    del t1
    print (Toto.instances)
    t3 = Toto(3)
    print (Toto.instances)
    del t3
    print (Toto.instances)
     
    print ('done')
    raw_input('fin\n')
    Output
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    [<weakproxy at 0xb76191bc to Toto at 0xb75c3b4c>, <weakproxy at 0xb75c2dc4 to Toto at 0xb75c3b6c>]
    __del__(Toto: number=1)
    [<weakproxy at 0xb75c2dc4 to Toto at 0xb75c3b6c>]
    [<weakproxy at 0xb75c2dc4 to Toto at 0xb75c3b6c>, <weakproxy at 0xb76191bc to Toto at 0xb75c3b4c>]
    __del__(Toto: number=3)
    Exception ReferenceError: 'weakly-referenced object no longer exists' in <bound method Toto.__del__ of <__main__.Toto object at 0xb75c3b4c>> ignored
    [<weakproxy at 0xb75c2dc4 to Toto at 0xb75c3b6c>, <weakproxy at 0xb76191bc to NoneType at 0x826c758>]
    done
    fin
    
    __del__(Toto: number=2)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    from sys import version
     
    if version.startswith('3'):
        raw_input = input
     
    import weakref
     
    class Toto(object):
        instances = []
     
        def __init__(self, number):
            self.number = number
            self._px = weakref.proxy(self)
            self.instances.append(self._px)
     
        def __del__(self):
            print ('__del__(%s)' % self)
            self.instances.remove(self._px)
     
        def __str__(self):
            return 'Toto: number=%d' % self.number
     
    t1 = Toto(1)
    t2 = Toto(2)
    t3 = Toto(3)
    print (Toto.instances)
    del t3
    print (Toto.instances)
    print ('done')
    raw_input('fin\n')
    Output
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [<weakproxy at 0xb75621bc to Toto at 0x8be4b4c>, <weakproxy at 0x8be3dc4 to Toto at 0x8be4b6c>, <weakproxy at 0x8be3dec to Toto at 0x8be4b8c>]
    __del__(Toto: number=3)
    Exception ReferenceError: 'weakly-referenced object no longer exists' in <bound method Toto.__del__ of <__main__.Toto object at 0x8be4b8c>> ignored
    [<weakproxy at 0xb75621bc to Toto at 0x8be4b4c>, <weakproxy at 0x8be3dc4 to Toto at 0x8be4b6c>, <weakproxy at 0x8be3dec to NoneType at 0x826c758>]
    done
    fin
    
    __del__(Toto: number=2)
    Exception ReferenceError: 'weakly-referenced object no longer exists' in <bound method Toto.__del__ of <__main__.Toto object at 0x8be4b6c>> ignored
    __del__(Toto: number=1)

  7. #27
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 790
    Par défaut

    Le pire est que les erreurs ne sont pas remontées normalement: c'est juste un message dans stderr. Mon IDE ayant de plus la bonne idée d'afficher de ne pas afficher en séquence ce qui sort de stderr et de stdout, çà n'aide pas.
    Mais ce n'est pas une excuse.
    Désolé.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  8. #28
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonjour,

    Pas grave: moi aussi j'ai écrit une boulette.
    Comme le signale dividee le callback est bien après le del. C'est d'ailleurs bien visible lorsque le callback est une méthode de la weak référence : le proxy l'interdit par un ReferenceError.

    @+

  9. #29
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Bonsoir,

    un grand merci à vous deux, wiztricks et PauseKawa. Les choses s'éclairent un peu.

    1)
    Dans les tests que j'ai fait, il ne me semble pas que __del__ soit appelé avant le callback; malgré cela, la weakref est parfois déjà invalide dans le callback:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    import weakref
     
    class WeakList(list):
     
        def append(self, val):
            list.append(self, weakref.proxy(val, self.remove))
     
        def remove(self, ref):
            print "remove"
            list.remove(self, ref)
     
    class Toto(object):
        instances = WeakList()
     
        def __init__(self,n):
            self.n = n
            self.instances.append(self)
     
        def __del__(self):
            print "__del__", self.n
     
     
    t1 = Toto(1)
    t2 = Toto(2)
    del t2
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    remove
    Exception ReferenceError: 'weakly-referenced object no longer exists' in <bound method WeakList.remove of [<weakproxy at 02AB1840 to Toto at 02AB2B70>, <weakproxy at 02AB1870 to NoneType at 1E1EA16C>]> ignored
    __del__ 2
    En tout cas quand la doc dit "... the weak reference callback (if any) finds the object still alive" cela me semble clairement erroné. L'objet est peut-être still alive mais le callback a du mal à trouver le cake...

    2)
    L'exception ne remonte pas correctement quand elle se produit dans le callback, mais sinon ça fonctionne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >> class Toto:
    ... 	x = 1
    ... 	
    >>> t = Toto()
    >>> r = weakref.proxy(t)
    >>> del t
    >>> r.x
    Traceback (most recent call last):
      File "<interactive input>", line 1, in <module>
    ReferenceError: weakly-referenced object no longer exists
    C'est probablement volontaire; ça ne semble pas être une très bonne idée de lever une exception dans un callback...

    3)
    Je suppose que l'exception est levée par list.remove parce qu'il essaie d’appeler __eq__ sur le proxy ?

    4)
    Contrairement à ce que dit wiztricks, je dirais que c'est le fait d'utiliser un proxy plutôt qu'une (weak-)ref qui est très moyen. Avec des refs, on peut utiliser le callback pour enlever des élements sans problème; même si la ref est invalide cela ne gène pas. D'ailleurs, l'implémentation de WeakSet de la lib standard utilise bien un set() de ref et un callback (mais elle est plus complexe car elle délaie les suppressions lorsqu'un itérateur est actif). Il est même dit que cela devrait être relativement thread-safe. LOL

  10. #30
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonjour dividee,

    En fait je ne pense pas avoir écrit une si grosse boulette.
    Le destructeur de l'objet doit être appelé après la suppression de la référence (ce qui entraîne la callback)

    L'idée d'une WeakList est bonne à condition de ne pas tenter d’accéder à l'objet mais plutôt au (si susceptible) proxy.

    @+

  11. #31
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Bah de toute façon c'est moi qui ait écrit la boulette initiale

    Un point intéressant que j'ai observé dans le code de WeakSet:

    Utiliser une méthode du WeakSet comme callback est problématique: si le WeakSet lui-même est supprimé alors qu'il n'est pas vide, lorsque les références qu'il contenait encore seront libérées, le callback sera appelé alors que self (le WeakSet) n'existera plus.

    Une méthode de classe ou statique ne conviendrait pas non plus car ici on veut pouvoir instancier plusieurs WeakSets indépendants les uns des autres.

    Pour cette raison, le callback n'est pas défini comme une méthode de WeakSet mais une fonction placée dans son __dict__ à laquelle on lie self lui-même par une weakref dans __init__, ce qui permet de vérifier si le Weakset existe toujours au moment de l'appel:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    class WeakSet(object):
        def __init__(self, data=None):
            self.data = set()
            def _remove(item, selfref=ref(self)):
                self = selfref()
                if self is not None:
                    if self._iterating:
                        self._pending_removals.append(item)
                    else:
                        self.data.discard(item)
            self._remove = _remove
            # A list of keys to be removed
            self._pending_removals = []
            self._iterating = set()
            if data is not None:
                self.update(data)
    # reste de la classe...
    C'est du grand art; je n'aurais jamais pensé à un truc pareil...

    [edit]
    En y repensant, finalement, je me demande si c'est vraiment pour cette raison... Si remove était une méthode de WeakSet, utilser self.remove comme callback devrait empêcher la libération de l'instance tant qu'il contient encore des weakref actives, non ?
    Il y a peut-être une autre raison...

  12. #32
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 790
    Par défaut
    Salut,

    En y repensant, finalement, je me demande si c'est vraiment pour cette raison... Si remove était une méthode de WeakSet, utilser self.remove comme callback devrait empêcher la libération de l'instance tant qu'il contient encore des weakref actives, non ?
    A la base cela permet de faire de détruire le weakset (et libérer les listes de ref qu'il contient) tout en permettant aux callbacks d'avoir ce qu'il faut pour s'exécuter correctement dans un contexte multithread: nombre de ces opérations ne sont pas atomiques.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  13. #33
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Merci wiztricks.

    Ce que j'avais oublié de considérer, c'est que si le WeakSet est détruit, les weakrefs le sont aussi, et qu'il n'y a donc plus lieu d'appeler le callback... sauf qu'effectivement dans un contexte multithread le callback pourrait être appelé à un moment inopportun...

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. [WD17] Poo : Liste des instances d'une classe
    Par R&B dans le forum WinDev
    Réponses: 2
    Dernier message: 29/03/2012, 16h22
  2. afficher liste des eleve d'une classe d un tableau T
    Par clem62173 dans le forum VB 6 et antérieur
    Réponses: 19
    Dernier message: 10/11/2009, 13h20
  3. Liste les instances d'une classe
    Par Mucho dans le forum Langage
    Réponses: 2
    Dernier message: 12/09/2009, 18h24
  4. Nommer des instances d'une classe dynamiquement ?
    Par Demosis dans le forum Langage
    Réponses: 4
    Dernier message: 04/11/2007, 15h22
  5. Réponses: 9
    Dernier message: 18/10/2007, 21h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo