猴子修补@property

dec*_*eze 38 python monkeypatching python-3.x

是否有可能修补@property我无法控制的类实例的值?

class Foo:
    @property
    def bar(self):
        return here().be['dragons']

f = Foo()
print(f.bar)  # baz
f.bar = 42    # MAGIC!
print(f.bar)  # 42
Run Code Online (Sandbox Code Playgroud)

显然,上述尝试分配时会产生错误f.bar.有# MAGIC!可能吗?这个实现细节@property是一个黑盒子,而不是间接的猴子可修补.需要替换整个方法调用.它只需要影响单个实例(如果不可避免,类级别修补就可以,但改变后的行为必须只选择性地影响给定的实例,而不是该类的所有实例).

Mar*_*nen 20

子类基类(Foo)并使用__class__属性更改单个实例的类以匹配新的子类:

>>> class Foo:
...     @property
...     def bar(self):
...         return 'Foo.bar'
...
>>> f = Foo()
>>> f.bar
'Foo.bar'
>>> class _SubFoo(Foo):
...     bar = 0
...
>>> f.__class__ = _SubFoo
>>> f.bar
0
>>> f.bar = 42
>>> f.bar
42
Run Code Online (Sandbox Code Playgroud)


kzh*_*kzh 9

from module import ClassToPatch

def get_foo(self):
    return 'foo'

setattr(ClassToPatch, 'foo', property(get_foo))
Run Code Online (Sandbox Code Playgroud)

  • 你似乎是一个声誉很高的成员,很抱歉打破了这个.我很确定你明白,如果你能详细说明你编写的算法的内容/方式/原因,那对任何人都会很好,也很有益. (4认同)

fra*_*lau 9

要对属性进行猴子修补,还有一种更简单的方法:

from module import ClassToPatch

def get_foo(self):
    return 'foo'

ClassToPatch.foo = property(get_foo)
Run Code Online (Sandbox Code Playgroud)

  • 问题是如何覆盖现有属性。这个答案与此无关。 (2认同)