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 :

Descripteurs et obsfucation d'attributs d'objets


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 Descripteurs et obsfucation d'attributs d'objets
    Salut.

    Je n'ai jamais vraiment utilisé de descripteurs personnalisés, mais je me demande si par un jeu de cache-cache, il est toujours possible d'accéder aux valeurs mémorisées dans le descripteur (__dict__).

    Pour le moment, je n'en suis qu'à faire des tests, voici en exemple à quoi je fais allusion.

    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
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    class ConstantixError(AttributeError):
        def __str__(self):
            return 'Constant can not be set again'
     
     
    class IntervalixError(ValueError):
        def __str__(self):
            return 'Value is not between {} and {}, got {}'.format(*self.args)
     
     
    class PositivixError(ValueError):
        def __str__(self):
            return 'Value can\'t be lower than 0'
     
     
    class Basix:
        __id = 0
        def __init__(self):
            self._id = Basix.__id
            Basix.__id += 1
     
        def __set__(self, obj, value):
            self.__dict__[self.get_id(obj)] = value
     
        def __get__(self, obj, type_obj):
            # return self.__dict__.get(self.get_id(obj), None)
            try:
                return self.__dict__[self.get_id(obj)]
            except KeyError:
                raise AttributeError('Value is not set')
     
        def get_id(self, obj):
            return '{}_{}'.format(id(obj), self._id)
     
     
    class Positivix(Basix):
        def __set__(self, obj, value):
            try:
                value = int(value)
                assert value >= 0
            except ValueError:
                raise ValueError('Value is not integer')
            except AssertionError:
                raise PositivixError
            super().__set__(obj, value)
     
     
    class Constantix(Basix):
        def __set__(self, obj, value):
            try:
                self.__get__(obj, value)
            except AttributeError:
                super().__set__(obj, value)
            else:
                raise ConstantixError
     
     
    class Intervalix(Basix):
        def __init__(self, min_value, max_value):
            self.__min = min_value
            self.__max = max_value
            super().__init__()
     
        def __set__(self, instance, value):
            try:
                assert self.__min <= value <= self.__max
            except TypeError:
                raise
            except AssertionError:
                raise IntervalixError(self.__min, self.__max, value)
            super().__set__(instance, value)
     
     
    if __name__ == '__main__':
     
        class BaseTest:
            CONST = Constantix()
            bas = Intervalix(1, 10)
            haut = Intervalix(40, 50)
            nombre = Positivix()
     
        class A(BaseTest):
            def __init__(self):
                self.CONST = 'coucou A'
                self.bas = 1
                self.haut = 40
                self.nombre = 0
     
        class B(BaseTest):
            def __init__(self):
                self.CONST = 'coucou B'
                self.bas = 5
                self.haut = 44
                self.nombre = 8
     
        a = A()
        b = B()
     
        for obj in (b, a):
            print(obj.__class__, obj.CONST, obj.bas, obj.haut, obj.nombre)
     
        try:
            a.CONST = 'boum'
        except Exception as e:
            print(e)
     
        for v in ('a', 1.2, -1, 8):
            try:
                a.bas = v
            except Exception as e:
                print(v, e)
            else:
                print('a.bas =', a.bas)
     
        print('bas')
        for obj in (a, b):
            print(obj.__class__, obj.bas)
     
        a.nombre = 41
        print('nombre', a.nombre, b.nombre)
    Dons ce script, les attributs ne sont plus enregistrés dans les __dict__ des objets des classes instanciées a et b, mais dans le __dict__ de Basix (bon, c'est sans doute pas une bonne idée). Pour peu que l'on arrive à deviner quel attribut correspond à quel identifiant du __dict__, est-il encore possible d'accéder au __dict__ du descripteur ailleurs que dans Basix (ou classes dérivées) ? je ne suis pas certain d'être bien clair dans mes propos.

    Edit: Je ne comprends pas pourquoi la coloration syntaxique ne fonctionne pas.

  2. #2
    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,

    Citation Envoyé par bistouille Voir le message
    est-il encore possible d'accéder au __dict__ du descripteur ailleurs que dans Basix (ou classes dérivées) ?
    Je dirais que non... mais le plus simple est de récupérer le nombre de références (via sys.getrefcount) et de voir si on les identifie toutes.

    Sinon, il y a un soucis ici:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        def __set__(self, obj, value):
            self.__dict__[self.get_id(obj)] = value
    L'identifiant d'un objet est garanti unique tant que l'objet existe mais il pourra être ré-utilisé dès que l'objet a été détruit. Dit autrement, on peut se retrouver avec les données d'un objet précédent (et on ne va pas s'en sortir juste avec un weakvaluedictionary).

    je ne suis pas certain d'être bien clair dans mes propos.
    voilà.

    - 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
    Salut.

    Merci des précisions.

    Citation Envoyé par wiztricks Voir le message
    Sinon, il y a un soucis ici:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        def __set__(self, obj, value):
            self.__dict__[self.get_id(obj)] = value
    L'identifiant d'un objet est garanti unique tant que l'objet existe mais il pourra être ré-utilisé dès que l'objet a été détruit. Dit autrement, on peut se retrouver avec les données d'un objet précédent (et on ne va pas s'en sortir juste avec un weakvaluedictionary).
    Ah en effet, je n'avais pas pensé à ce léger gros problème, je vais m'en tenir à garder les références des attributs dans leurs propres objets, ce n'est pas viable de procéder comme j'ai fait dans ces tests.

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

Discussions similaires

  1. Utilisation attributs d'objets d'1 ArrayList
    Par lylandra6 dans le forum Collection et Stream
    Réponses: 23
    Dernier message: 09/09/2010, 14h17
  2. Tester le lazy d'un attribut d'objet
    Par Nertios dans le forum Hibernate
    Réponses: 2
    Dernier message: 21/04/2010, 06h33
  3. Réponses: 1
    Dernier message: 29/09/2008, 16h21
  4. Une Liste d'objets comme attribut d'objet
    Par koomkoom dans le forum Langage
    Réponses: 1
    Dernier message: 31/08/2008, 19h20
  5. Tri d'objets par l'un des attributs des objets
    Par womannosky dans le forum Général Java
    Réponses: 5
    Dernier message: 27/01/2008, 19h29

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