如何在现有对象上更改属性的基础getter / setter / deleter?

时间:2019-01-02 20:43:41

标签: python-3.x properties getter-setter descriptor

通常,基本上可以随意添加或修改对象属性,但是似乎无法修改现有的对象属性来更改底层的getter / setter / deleter函数。

例如,具有以下类别:

class Foo:
    def __init__(self, x):
        self._x = x
    def get_x(self):
        print("get_x function!")
        return self._x
    @property
    def x(self):
        print("x property getter!")
        return self._x

用其他函数替换get_x很简单:

In [1]: foo = Foo('foo')
   ...: foo.get_x()
get_x function!
Out[1]: 'foo'

In [2]: foo.get_x = lambda: 'something else'
   ...: foo.get_x()
Out[2]: 'something else'

将外部函数绑定到对象也不难,因此它可以接受self

def bind(instance, value):
    return value.__get__(instance, instance.__class__)

然后:

In [3]: foo.get_x = bind(foo, lambda self: 'modified ' + self._x)
   ...: foo.get_x()
Out[3]: 'modified foo'

我知道此分配仅覆盖原始定义,而不是实际替换它,但是

但是,如果我尝试替换x,则该属性已经可以控制=setattr。我可以尝试类似的东西:

In [4]: foo.x = property(bind(foo, lambda self: 'modified ' + self._x))
AttributeError: can't set attribute

但是即使它工作了也基本上没有意义,因为结果是属性对象本身而不是对其的访问:

In [5]: foo.y = property(bind(foo, lambda self: 'modified ' + self._x))
   ...: foo.y
Out[5]: <property at 0x220e9780548>

在修改基础类的工作原理时,我不想更改所有 实例,只是其中之一:

In [6]: foo.__class__.x = property(lambda self: 'modified ' + self._x)
   ...: foo.x
Out[6]: 'modified foo'

In [7]: bar = Foo('bar')
   ...: bar.x # don't want this to have changed
Out[7]: 'modified bar'

如何更改现有对象上属性的基础getter / setter / deleters?

0 个答案:

没有答案