我知道我可以通过执行以下操作动态地向对象添加实例方法:
import types
def my_method(self):
# logic of method
# ...
# instance is some instance of some class
instance.my_method = types.MethodType(my_method, instance)
稍后我可以打电话给instance.my_method()
,自我将被正确绑定,一切正常。
现在,我的问题:如何做同样的事情来获得用@property来装饰新方法的行为?
我猜想会像:
instance.my_method = types.MethodType(my_method, instance)
instance.my_method = property(instance.my_method)
但是,执行instance.my_method
会返回一个属性对象。
答案 0 :(得分:35)
property
描述符对象需要存在实例中的类,而不是,才能获得您想要的效果。如果您不想更改现有类以避免更改其他实例的行为,则需要创建“每个实例类”,例如:
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))
我正在使用一个属性标记这些特殊的“per-instance”类,以避免在同一个实例上进行多次addprop
调用时不必要地制作多个。
请注意,与property
的其他用途一样,您需要在游戏中使用新式(通常通过直接或间接从object
继承而获得) ,不古老的遗留风格(在Python 3中删除),默认情况下分配给没有基础的类。
答案 1 :(得分:3)
由于这个问题不是要求仅添加到特定实例, 可以使用以下方法向类添加属性,这会将属性公开给YMMV类的所有实例。
cls = type(my_instance)
cls.my_prop = property(lambda self: "hello world")
print(my_instance.my_prop)
# >>> hello world
注意:添加另一个答案,因为我认为@Alex Martelli虽然正确,但是通过创建一个包含该属性的新类来实现所需的结果,这个答案旨在更加直接/直接没有抽象出自己的方法。