and - Añadiendo dinámicamente @property en python
python class properties (2)
Sé que puedo agregar dinámicamente un método de instancia a un objeto haciendo algo como:
import types
def my_method(self):
# logic of method
# ...
# instance is some instance of some class
instance.my_method = types.MethodType(my_method, instance)
Más adelante, puedo llamar a instance.my_method()
y self se enlazará correctamente y todo funcionará.
Ahora, mi pregunta: ¿cómo hacer exactamente lo mismo para obtener el comportamiento que decoraría el nuevo método con @property?
Supongo que algo como:
instance.my_method = types.MethodType(my_method, instance)
instance.my_method = property(instance.my_method)
Pero, al hacer esa instance.my_method
, mi instance.my_method
devuelve un objeto de propiedad.
Dado que esta pregunta no se refiere solo a la adición a una instancia específica, se puede usar el siguiente método para agregar una propiedad a la clase, esto expondrá las propiedades a todas las instancias de la clase YMMV.
cls = type(my_instance)
cls.my_prop = property(lambda self: "hello world")
print(my_instance.my_prop)
# >>> hello world
Nota: Agregar otra respuesta porque creo que @Alex Martelli, aunque correcta, está logrando el resultado deseado al crear una nueva clase que posee la propiedad, esta respuesta pretende ser más directa / directa sin abstraer lo que sucede en su propio método.
El objeto descriptor de property
debe vivir en la clase , no en la instancia , para tener el efecto que desea. Si no desea modificar la clase existente para evitar alterar el comportamiento de otras instancias, deberá crear una "clase por instancia", por ejemplo:
def addprop(inst, name, method):
cls = type(inst)
if not hasattr(cls, ''__perinstance''):
cls = type(cls.__name__, (cls,), {})
cls.__perinstance = True
inst.__class__ = cls
setattr(cls, name, property(method))
Estoy marcando estas clases especiales "por instancia" con un atributo para evitar hacer innecesariamente varias si estás haciendo varias llamadas addprop
en la misma instancia.
Tenga en cuenta que, al igual que para otros usos de la property
, necesita que la clase en juego sea de estilo nuevo (que suele obtenerse heredando directa o indirectamente de un object
), no el estilo antiguo heredado (colocado en Python 3) que se asigna de forma predeterminada a un Clase sin bases.