Voici un moyen d'éviter l'hypothèse selon laquelle
tous les utilisateurs sont des adultes consentants, et sont donc responsables de l'utilisation correctement les choses.
veuillez voir ma mise à jour ci-dessous
Utilisation de @property
est très verbeux, par exemple :
class AClassWithManyAttributes:
'''refactored to properties'''
def __init__(a, b, c, d, e ...)
self._a = a
self._b = b
self._c = c
self.d = d
self.e = e
@property
def a(self):
return self._a
@property
def b(self):
return self._b
@property
def c(self):
return self._c
# you get this ... it's long
Utilisation de
Pas de trait de soulignement : c'est une variable publique.
Un trait de soulignement : c'est une variable protégée.
Deux traits de soulignement : c'est une variable privée.
Sauf le dernier, c'est une convention. Vous pouvez toujours, si vous essayez vraiment, accéder aux variables avec un double soulignement.
Alors, que faisons-nous ? Devons-nous renoncer à avoir des propriétés en lecture seule en Python ?
Regardez ! read_only_properties
Le décorateur à la rescousse !
@read_only_properties('readonly', 'forbidden')
class MyClass(object):
def __init__(self, a, b, c):
self.readonly = a
self.forbidden = b
self.ok = c
m = MyClass(1, 2, 3)
m.ok = 4
# we can re-assign a value to m.ok
# read only access to m.readonly is OK
print(m.ok, m.readonly)
print("This worked...")
# this will explode, and raise AttributeError
m.forbidden = 4
Vous demandez :
Où se trouve read_only_properties
venant de ?
Content que vous demandiez, voici la source pour Propriétés en lecture seule :
def read_only_properties(*attrs):
def class_rebuilder(cls):
"The class decorator"
class NewClass(cls):
"This is the overwritten class"
def __setattr__(self, name, value):
if name not in attrs:
pass
elif name not in self.__dict__:
pass
else:
raise AttributeError("Can't modify {}".format(name))
super().__setattr__(name, value)
return NewClass
return class_rebuilder
mise à jour
Je ne m'attendais pas à ce que cette réponse suscite autant d'attention. C'est surprenant. Cela m'a encouragé à créer un paquet que vous pouvez utiliser.
$ pip install read-only-properties
dans votre shell python :
In [1]: from rop import read_only_properties
In [2]: @read_only_properties('a')
...: class Foo:
...: def __init__(self, a, b):
...: self.a = a
...: self.b = b
...:
In [3]: f=Foo('explodes', 'ok-to-overwrite')
In [4]: f.b = 5
In [5]: f.a = 'boom'
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-5-a5226072b3b4> in <module>()
----> 1 f.a = 'boom'
/home/oznt/.virtualenvs/tracker/lib/python3.5/site-packages/rop.py in __setattr__(self, name, value)
116 pass
117 else:
--> 118 raise AttributeError("Can't touch {}".format(name))
119
120 super().__setattr__(name, value)
AttributeError: Can't touch a