Conflicto de función entre __get__ y __getattribute__
Estoy escribiendo código en Python 3.9 y recientemente descubrí los descriptores.
He creado una clase que se ve así:
import threading
class OuterClass():
class DecoratorTest():
def __init__(self, fget, fset=None) -> None:
self.fget = fget
self.fset = fset
self.event = threading.Event()
def __getattribute__(self, name: str):
return object.__getattribute__(self, name)
def __get__(self, obj, objtype=None):
return self.fget(obj)
def __set__(self, obj, value):
self.fset(obj, value)
self.event.set()
self.event.clear()
def setter(self, fset):
return type(self)(self.fget, fset)
def __init__(self):
self.random_value = 10
@DecoratorTest
def test_property(self):
return self.random_value * 2
@test_property.setter
def test_property(self, value):
self.random_value = value
Mi intención es tener un decorador que agregue un evento a la propiedad decorada, de modo que cuando se cambie la propiedad, se establezca el evento. Este es un ejemplo de cómo lo usaría:
class_iteration = OuterClass()
def test_funct():
while True:
class_iteration.test_property.event.wait()
print("¡Cambió!")
threading.Thread(target=test_funct).start()
class_iteration.test_property = 100
El problema es que cuando intento obtener el evento, considera que class_iteration.test_property
es un objeto int, por lo que arroja un error. Me pregunto si hay alguna manera de evitar el __get__
cuando se usa __getattribute__
, para poder acceder a la variable event
, o si necesito cambiar completamente mi enfoque.
davy.ai
Como experto en IT especializado en Python, sugeriría que el problema aquí radica en la implementación de
__getattribute__
en la claseDecoratorTest
. Tal y como está escrito el código en este momento,__getattribute__
siempre pasará por alto el método__get__
reemplazado cuando se llame en una instancia de la claseDecoratorTest
, y en su lugar retornará directamente el atributo solicitado desde el atributo__dict__
del objeto.Para solucionar este problema, podrías modificar el método
__getattribute__
para llamar explícitamente al método__get__
del descriptor del objeto si existe, antes de recurrir al comportamiento por defecto de retornar el atributo directamente desde el atributo__dict__
del objeto. Aquí tienes una implementación modificada deDecoratorTest
que debería lograr el comportamiento deseado:Con esta implementación actualizada de
DecoratorTest
, los métodos__get__
y__set__
deberían ser llamados correctamente al acceder a la propiedad decorada, y se debería poder acceder al atributoevent
como se espera.