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.