在运行时覆盖@property getter

cam*_*ddc 0 python overriding properties

有没有办法在Python中覆盖运行时的@property getter?

我希望我的类有一个"复杂"的getter,它运行一些代码并返回一个可以改变的值.但是,如果由于某种原因我将该变量设置为其他东西,我希望它始终返回该值.

例如:

class Random(object):
    @property
    def random_number():
        return random.randint(0,10)


    @random_number.setter
    def random_number(value):
        # Overlord says that random must always return `value`
        (((I don't know that to do here)))


>>>r = Random()
>>>r.random_number
>>>(returns something between 0,10)

>>>r.random_number = 4 # Confirmed by dice roll
>>>r.random_number
>>>4 (always)
Run Code Online (Sandbox Code Playgroud)

我知道我可以使用像'force_value'这样的实例var,我总是检查我的getter,但我想尽可能避免这种情况.

理想情况下,我的setter函数可以做类似的事情

self.random_number.getter = lambda:4
Run Code Online (Sandbox Code Playgroud)

但我不知道如何做到这一点.

Mar*_*ers 5

您不能"覆盖"实例级别的属性,因为属性是数据描述符(它具有两个__get____set__钩子).

这意味着您的getter 必须检查实例属性.这并不像听起来那么痛苦:

class Random(object):
    @property
    def random_number(self):
        if hasattr(self, '_override'):
            return self._override
        return random.randint(0,10)

    @random_number.setter
    def random_number(self, value):
        # Overlord says that random must always return `value`
        self._override = value
Run Code Online (Sandbox Code Playgroud)

你甚至可以添加一个删除器:

    @random_number.deleter
    def random_number(self):
        if hasattr(self, '_override'):
            del self._override
Run Code Online (Sandbox Code Playgroud)

另一种方法是创建自己的备用描述符类,它不实现__setter__钩子,因此您可以直接在实例上设置属性并使其覆盖描述符.但对于您的用例,只使用显式setter似乎更简单.