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 :

slots, héritage, références


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Billets dans le blog
    1
    Par défaut slots, héritage, références
    Salut,

    J'ai fait quelques tests avec les slots, même si pour le moment j'en ai pas trop besoin, peut-être ultérieurement.
    Bon pour être franc le modèle objet python, j'aime bien certains aspects, mais d'autres je déteste.

    Le fonctionnement lors de l'héritage des slots me laisse vraiment circonspect à tel point que je me demande s'il y a vraiment des programmeurs qui les utilisent vu les contraintes que cela engendre.

    Si on fait un truc basique, ok, c'est cool, ça fonctionne.

    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
    class A :
        __slots__ = ['_var']
        def __init__(self, valeur) : 
            self._var = valeur
     
        @property
        def var(self) :
            return self._var
     
    class B(A) :
        def __init__(self, valeur) :
            A.__init__(self, valeur)
     
    a = A('A')
    b = B('B')
    print(a.var, b.var) # A, B
    Mais dès lors, que l'on veut un peu complexifier.

    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
    class A :
        __slots__ = {'_var':None}
        def __init__(self, valeur) :
            self.__slots__['_var'] = valeur
     
        def __setattr__(self, cle, valeur) :
            raise NotImplementedError
     
        @property
        def var(self) :
            return self.__class__.__slots__['_var']
     
    class B(A) :
        def __init__(self, valeur) :
            A.__init__(self, valeur)
     
    a = A('A')
    b = B('B')
    print(a.var, b.var) # B, B ...
    Ok, la doc est claire, faut ajouter __weakreference__ aux classes filles pour avoir un fonctionnement correct.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    __slots__ = {'__weakreference__':None}
    Mais c'est moisi non ce truc ?
    Y'a pas un subterfuge pour induire ce comportement depuis la classe mère ?

    Et d'ailleurs, je me demande si on ne pourrait pas se servir de ce comportement de références implicite comme singleton.

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 736
    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 736
    Par défaut
    Salut,

    Une variable de classe mutable reste une variable de classe mutable (quelque soit la façon tordue que vous utiliser pour y accéder):
    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
     
    class A :
        dd = {'_var':None}
        def __init__(self, valeur) :
            self.dd['_var'] = valeur
     
        def __setattr__(self, cle, valeur) :
            raise NotImplementedError
     
        @property
        def var(self) :
            return self.__class__.dd['_var']
     
    class B(A) :
     
        def __init__(self, valeur) :
            A.__init__(self, valeur)
     
    a = A('A')
    b = B('B')
    print(a.var, b.var) # B, B ...

    Citation Envoyé par bistouille
    Et d'ailleurs, je me demande si on ne pourrait pas se servir de ce comportement de références implicite comme singleton.
    Et un singleton est toujours réalisé avec une(des) variable(s) de classe(s).

    Citation Envoyé par bistouille
    J'ai fait quelques tests avec les slots, même si pour le moment j'en ai pas trop besoin, peut-être ultérieurement.
    Bon pour être franc le modèle objet python, j'aime bien certains aspects, mais d'autres je déteste.
    Je dirais qu'il faut utiliser les slots seulement quand on en a besoin:
    By default, instances of both old and new-style classes have a dictionary for attribute storage. This wastes space for objects having very few instance variables. The space consumption can become acute when creating large numbers of instances.
    Economiser l'espace mémoire lorsqu'on doit créer beaucoup d'instances d'une classe ayant peu d'attributs (exemple: une classe Point ou Vecteur dans un plan pour une bibliothèque 2D/3D).

    Les restrictions dans l'utilisation des slots ne sont pas faciles à prendre en compte dans une étape d'optimisation: il risque d'y avoir pas mal de chose à refaire. Et c'est vrai que le programmeur Python code plutôt avant d'avoir finaliser le design, ce qui lui permet difficilement de profiter de ce genre de fonctionnalités.

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

  3. #3
    Membre très actif

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Une variable de classe mutable reste une variable de classe mutable (quelque soit la façon tordue que vous utiliser pour y accéder)
    Mais

    Alors là, j'avais pas bien compris, je ne voyais pas __slots__ comme une variable de classe du tout, je pensais que c'était pour indiquer à python que l'on souhaitait se servir de __slots__ à la place de __dict__, et donc qu'on substituait __slots__ à __dict__ en ayant le même comportement interne dans l'objet sans le côté dynamique de __dict__

    Citation Envoyé par wiztricks Voir le message
    Et un singleton est toujours réalisé avec une(des) variable(s) de classe(s).
    Ça je le savais déjà, mais merci tout de même

    Citation Envoyé par wiztricks Voir le message
    Economiser l'espace mémoire lorsqu'on doit créer beaucoup d'instances d'une classe ayant peu d'attributs (exemple: une classe Point ou Vecteur dans un plan pour une bibliothèque 2D/3D).
    Intéressant, du coup je crois que je vais voir pour l’utiliser dans certains de mes scripts comportant ce cas de figure.

    Merci

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 736
    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 736
    Par défaut
    Citation Envoyé par bistouille Voir le message
    Alors là, j'avais pas bien compris, je ne voyais pas __slots__ comme une variable de classe du tout, je pensais que c'était pour indiquer à python que l'on souhaitait se servir de __slots__ à la place de __dict__, et donc qu'on substituait __slots__ à __dict__ en ayant le même comportement interne dans l'objet sans le côté dynamique de __dict__
    En écrivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> class A:
    ...    __slots__ = ('var',)
    ...
    on crée une variable de classe (__slots__) à laquelle on assigne la liste des noms d'attributs d'instance "autorisés".
    On supprime le __dict__ assigné lors de la création de l'instance et la mécanique se cache dans des "properties":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> A.var.__set__(a, 1)  ## <=> a.var = 1
    >>> A.var.__get__(a, A) 
    1
    >>>
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre très actif

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Billets dans le blog
    1
    Par défaut
    Je comprends un peu mieux désormais, mais c'est assez déroutant.

    Si on utilise un slot, la variable d'instance garde toujours la référence à la variable de classe, donc si on modifie la variable de classe, la variable d'instance est aussi modifiée, je trouve cela assez dangereux comme comportement, avis qui n'engage que moi.

    Ce qui est marrant, c'est que j'ai vu qu'on pouvait fourrer le __dict__ dans __slots__, après je ne sais pas si __slots__ garde toujours son intérêt en faisant ceci, si c'est le cas, ça peut être intéressant d'utiliser ce contournement aux restrictions des slots.

    Bien merci wiztricks pour ces précisions.

  6. #6
    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
    Citation Envoyé par bistouille Voir le message
    Si on utilise un slot, la variable d'instance garde toujours la référence à la variable de classe, donc si on modifie la variable de classe, la variable d'instance est aussi modifiée, je trouve cela assez dangereux comme comportement, avis qui n'engage que moi.
    Non ce n'est pas ce qui se passe. Quand Python ne trouve pas une variable d'instance, il cherche une variable de classe du même nom.

    Donc quand tu écris self.__slots__['_var'] = valeur, tu modifies la variable de classe __slots__, car il n'y a pas de variable d'instance de ce nom-là. Le résultat est le même que si tu écris self.__class__.__slots__['_var'] = valeur.

    J'ai l'impression que tu confonds la variable de classe __slots__ avec les attributs d'instances qu'elle définit.

    Ca n'a pas de sens d'assigner un dictionnaire à __slots__. Cela passe car il attend un itérable, et un dictionnaire est un itérable, mais ça a le même effect qu'utiliser une liste contenant les clés du dictionnaire. Les valeurs du dictionnaires sont ignorées. Tu retrouves certes ton dictionnaire dans la variable de classe __slots__, mais, une fois que la classe est créée, c'est une variable de classe ordinaire qui n'a plus de mécanisme particulier associé. Du coup ça n'a pas de sens non plus de modifier dynamiquement les __slots__, ils ne sont pas faits pour cela. Cela n'a pas de répercussion sur les variables d'instances.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 21
    Dernier message: 26/07/2011, 12h08
  2. Signals/Slots et héritage
    Par agh dans le forum Débuter
    Réponses: 1
    Dernier message: 18/04/2010, 16h36
  3. Réponses: 2
    Dernier message: 16/06/2009, 16h41
  4. Signals, slots et héritage
    Par Niak74 dans le forum Qt
    Réponses: 14
    Dernier message: 26/02/2009, 15h33
  5. Passge par référence & héritage
    Par jsatla dans le forum C++
    Réponses: 11
    Dernier message: 04/01/2006, 17h44

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