Quiero anular el acceso a una variable en una clase, pero devolver todas las demás normalmente. ¿Cómo logro esto con __getattribute__
?
Intenté lo siguiente (que también debería ilustrar lo que estoy tratando de hacer) pero obtengo un error de recursividad:
class D(object):
def __init__(self):
self.test=20
self.test2=21
def __getattribute__(self,name):
if name=='test':
return 0.
else:
return self.__dict__[name]
>>> print D().test
0.0
>>> print D().test2
...
RuntimeError: maximum recursion depth exceeded in cmp
super(D, self).__getattribute__(name)
super().__getattribute__(name)
en Python 3.En realidad, creo que desea utilizar el
__getattr__
método especial en su lugar.Cita de los documentos de Python:
Nota: para que esto funcione, la instancia no debe tener un
test
atributo, por lo que la líneaself.test=20
debe eliminarse.fuente
__getattr__
portest
sería inútil, ya que siempre lo encontraría "en los lugares habituales".Referencia del lenguaje Python:
Sentido:
Estás pidiendo un atributo llamado
__dict__
. Como es un atributo,__getattribute__
se llama para buscar__dict__
qué llamadas__getattribute__
qué llamadas ... yada yada yadaEl uso de las clases base
__getattribute__
ayuda a encontrar el atributo real.fuente
¿Estás seguro de que quieres usar
__getattribute__
? ¿Qué estás tratando de lograr realmente?La forma más sencilla de hacer lo que pide es:
o:
Editar:
D
tenga en cuenta que una instancia de tendría diferentes valores detest
en cada caso. En el primer casod.test
sería 20, en el segundo sería 0. Dejaré que usted averigüe por qué.Edit2: Greg señaló que el ejemplo 2 fallará porque la propiedad es de solo lectura y el
__init__
método intentó establecerla en 20. Un ejemplo más completo sería:Obviamente, como clase, esto es casi completamente inútil, pero te da una idea para seguir adelante.
fuente
Aquí hay una versión más confiable:
Llama al método __ getattribute __ desde la clase principal, y eventualmente regresa al objeto. __ getattribute __ método si otros ancestros no lo anulan.
fuente
Se llama antes de la búsqueda de puntos normal. Si sube
AttributeError
, llamamos__getattr__
.El uso de este método es bastante raro. Solo hay dos definiciones en la biblioteca estándar:
Mejores prácticas
La forma correcta de controlar mediante programación el acceso a un solo atributo es con
property
. La claseD
debe escribirse de la siguiente manera (con el establecedor y el eliminador opcionalmente para replicar el comportamiento previsto aparente):Y uso:
Una propiedad es un descriptor de datos, por lo que es lo primero que se busca en el algoritmo de búsqueda de puntos normal.
Opciones para
__getattribute__
Tiene varias opciones si es absolutamente necesario implementar la búsqueda para cada atributo a través de
__getattribute__
.AttributeError
, haciendo__getattr__
que se llame (si se implementa)super
para llamar a laobject
implementación de los padres (probablemente )__getattr__
Por ejemplo:
Lo que originalmente querías.
Y este ejemplo muestra cómo podría hacer lo que originalmente quería:
Y se comportará así:
Revisión de código
Tu código con comentarios. Tiene una búsqueda punteada de sí mismo en
__getattribute__
. Es por eso que obtiene un error de recursividad. Puede verificar si el nombre es"__dict__"
y usarsuper
para una solución alternativa, pero eso no cubre__slots__
. Dejaré eso como un ejercicio para el lector.fuente