在python中动态添加@property

rz.*_*rz. 18 python

我知道我可以通过执行以下操作动态地向对象添加实例方法:

import types
def my_method(self):
    # logic of method
# ...
# instance is some instance of some class
instance.my_method = types.MethodType(my_method, instance)
Run Code Online (Sandbox Code Playgroud)

后来我可以打电话instance.my_method(),自我将被正确绑定,一切正常.

现在,我的问题:如何做同样的事情来获得用@property装饰新方法的行为?

我猜是这样的:

instance.my_method = types.MethodType(my_method, instance)
instance.my_method = property(instance.my_method)
Run Code Online (Sandbox Code Playgroud)

但是,这样做会instance.my_method返回一个属性对象.

Ale*_*lli 37

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))
Run Code Online (Sandbox Code Playgroud)

我正在用一个属性标记这些特殊的"每个实例"类,以避免addprop在同一个实例上进行多次调用时不必要地制作多个类.

请注意,与其他用途一样property,您需要将游戏中的类设置为新样式(通常通过直接或间接继承获得object),而不是默认分配给没有类的古老遗留样式(在Python 3中删除)基地.

  • 我只是按照这个答案的链接,发现它非常有用.但是,也许是由于过去几年Python的变化,一些事情对我来说没有开箱即用.我不得不将`cls.hasattr('__ perinstance')`更改为`hasattr(cls,'__ instinstance')`,我必须在`if`块中添加一行:`inst .__ class__ = cls`.我希望这有助于任何看到这个答案的人让它为他们工作! (12认同)
  • @Blckknght:我没有看到原始答案是如何工作的,因为它不会在发生时将实例的类更改为新创建的"每个实例". (8认同)