【问题标题】:How to force the @property setter work only once?如何强制@property setter 只工作一次?
【发布时间】:2020-09-25 10:05:38
【问题描述】:

我有一个带有属性的类(在下面的玩具示例中为signature)。 必须进行一些验证,因此有一个 setter (@signature.setter)。

class Signature:
    def __init__(self, input_array):
        self.signature = input_array

    @property
    def signature(self):
        return self._signature

    @signature.setter
    def signature(self, input_array):
        arr = np.array(input_array)
        if arr.ndim > 1:
            raise ValueError("Only one-dimensional arrays are accepted!")
        arr = np.unique(arr)
        if any(arr <= 0):
            raise ValueError("Only positive numbers are accepted!")
        self._signature = arr
lst = [2,3,4]
s = Signature(lst)
s.signature
# array([2, 3, 4])

但是我可以写:

s.signature = [4, 5, 6]

一切都会很好,因为有一个@signature.setter

现在我想要保护 s.signature 在创建此具体对象后不被设置。

我应该在__new__ 中使用@property 吗?我该怎么做?

(我知道How to restrict setting an attribute outside of constructor? 的讨论,但那里没有二传手……)

【问题讨论】:

  • 不使用setter,为什么不移除setter,只在init期间设置_signature?否则,您可以在设置器中执行 if not self._signature 以仅在尚未定义的情况下更改 _signature
  • 如果您希望只通过__init__ 设置self.signature,为什么首先要有一个公共设置器?
  • 嗯...这很明显。现在我很难理解为什么这对我来说是个问题。抱歉打扰各位了……

标签: python oop


【解决方案1】:

如果尝试设置signature,您可以让设置器引发异常。只需使用不同的方法检查传递给__init__ 的值并设置它:

import numpy as np
​
class Signature:
    def __init__(self, input_array):
        self._check_and_set_signature(input_array)
​
    @property
    def signature(self):
        return self._signature
​
    @signature.setter
    def signature(self, value):
        raise ValueError("signature already set")
        
        
        
    def _check_and_set_signature(self, input_array):
        arr = np.array(input_array)
        if arr.ndim > 1:
            raise ValueError("Only one-dimensional arrays are accepted!")
        arr = np.unique(arr)
        if any(arr <= 0):
            raise ValueError("Only positive numbers are accepted!")
        self._signature = arr

示例运行:

lst = [2,3,4]
s = Signature(lst)
print(s.signature)
# array([2, 3, 4])
​
s.signature = [4, 5, 6]
[2 3 4]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-6-68b91a667238> in <module>
     30 # array([2, 3, 4])
     31 
---> 32 s.signature = [4, 5, 6]

<ipython-input-6-68b91a667238> in signature(self, value)
     11     @signature.setter
     12     def signature(self, value):
---> 13         raise ValueError("signature already set")
     14 
     15 

ValueError: signature already set

【讨论】:

    猜你喜欢
    • 2021-09-21
    • 2018-11-28
    • 2017-09-30
    • 2019-01-04
    • 2017-01-06
    • 2018-06-22
    • 2015-09-18
    • 2013-12-31
    • 1970-01-01
    相关资源
    最近更新 更多