Solución:
Generalmente, los programas de Python deben escribirse asumiendo que todos los usuarios son adultos que consienten y, por lo tanto, son responsables de usar las cosas correctamente ellos mismos. Sin embargo, en el raro caso en el que simplemente no tiene sentido que un atributo sea configurable (como un valor derivado o un valor leído de alguna fuente de datos estática), la propiedad de solo captador es generalmente el patrón preferido.
Solo mis dos centavos, Silas Ray está en el camino correcto, sin embargo, tuve ganas de agregar un ejemplo. 😉
Python es un lenguaje de tipo inseguro y, por lo tanto, siempre tendrá que confiar en los usuarios de su código para usar el código como una persona razonable (sensata).
Por PEP 8:
Utilice un guión bajo inicial solo para métodos no públicos y variables de instancia.
Para tener una propiedad de ‘solo lectura’ en una clase, puede hacer uso de la @property
decoración, necesitarás heredar de object
cuando lo haga para hacer uso de las clases de estilo nuevo.
Ejemplo:
>>> class A(object):
... def __init__(self, a):
... self._a = a
...
... @property
... def a(self):
... return self._a
...
>>> a = A('test')
>>> a.a
'test'
>>> a.a="pleh"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
Aquí hay una forma de evitar la suposición de que
todos los usuarios son adultos que consienten y, por lo tanto, son responsables de usar las cosas correctamente por sí mismos.
por favor mira mi actualización a continuación
Utilizando @property
, es muy detallado, por ejemplo:
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
Utilizando
Sin subrayado: es una variable pública.
Un subrayado: es una variable protegida.
Dos guiones bajos: es una variable privada.
Excepto el último, es una convención. Aún puede, si realmente se esfuerza, acceder a las variables con doble subrayado.
¿Asi que que hacemos? ¿Renunciamos a tener propiedades de solo lectura en Python?
¡Mirad! read_only_properties
decorador al rescate!
@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
Usted pregunta:
Dónde está
read_only_properties
¿procedente de?
Me alegro de que lo hayas preguntado, aquí está la fuente de read_only_properties:
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
actualizar
Nunca esperé que esta respuesta recibiera tanta atención. Sorprendentemente lo hace. Esto me animó a crear un paquete que puedas usar.
$ pip install read-only-properties
en tu caparazón de 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