【问题标题】:Accessing current value of property in setter在 setter 中访问属性的当前值
【发布时间】:2017-05-30 15:30:08
【问题描述】:

在 Python 中,是否可以在其 setter 中访问类变量的当前值

例如:

# Getter
@property
# ...

# Setter
@position.setter
def position(self, value):
    # Do something with current value...
    # self.position, self.__position, position and __position don't seem to work

    # Update position with the given value
    self.__position = value

    # Do something with the new value...

C# 中的等价物是:

private Position position;

public Position Position
{
    get
    {
        // ...
    }

    set
    {
        // Do something with the current value...

        // Update position field with given object
        position = value;

        // Do something with the new value...
    }
}

更新
这是一个最小、完整且可验证的示例,以更好地说明我的问题:

class C:
    def __init__(self):
        self.x = 2

    @property
    def x(self):
        return self.__x

    @x.setter
    def x(self, value):
        print(self.x)
        self.__x = value
        print(self.x)

c = C()

抛出以下错误:

AttributeError: 'C' object has no attribute '_C__x'

发生这种情况是因为 setter 尝试在更新变量之前打印变量的当前值,并且当 x__init__ 中设置为 2 时运行 setter,此时 x 之前没有被赋值(没有要打印的当前值)。

【问题讨论】:

  • 你是什么意思“似乎不起作用”?在您分配给它之前,self.__position 仍然是旧值,因此 self.position 也将访问旧值。
  • 这就是我的想法,但是尝试在 setter 中访问 self.positionself.__position 都会导致以下错误:AttributeError: 'GameObject' object has no attribute '_GameObject__position'。 (GameObject 是包含position 变量的类。)
  • 请给minimal reproducible example。还可以考虑放弃__double_underscore,因为名称修改会不必要地使事情复杂化。
  • 在制作MCV示例时,我发现在__init__中第一次设置变量时抛出了错误,此时变量尚未被赋值。如何检查这种情况?
  • @jonrsharpe 关于双下划线,我错误地认为在其设置器中更新类变量的值时需要它们。

标签: python class properties setter


【解决方案1】:

您在__init__ 中设置了self.x(使用setter)。但是在你的x.setterprint(self.x)(使用getter)之前实际设置你的值。

您可以定义一个默认值(例如作为类属性)以使其工作:

class C:
    __x = None

    def __init__(self):
        self.x = 2

    @property
    def x(self):
        return self.__x

    @x.setter
    def x(self, value):
        print(self.x)
        self.__x = value
        print(self.x)

>>> c = C()
None
2

请注意,双下划线变量受"name mangling" 约束,约定是使用单下划线变量。

另一种方法是通过try 访问它,如果它不可用,则返回其他内容(或执行其他操作):

class C:
    def __init__(self):
        self.x = 2

    @property
    def x(self):
        try:
            return self.__x
        except AttributeError:
            # I return "None" here but you could also do something else
            return None

    @x.setter
    def x(self, value):
        print(self.x)
        self.__x = value
        print(self.x)

产生相同的结果:

>>> c = C()
None
2

【讨论】:

  • 只是想知道,有没有办法做到这一点而不使变量“静态”(不初始化 __x__init__ 之外)?
  • @Ruben9922 我添加了另一种在“getter”中捕获异常的方法。这是否回答你的问题?请注意,您还可以在 setter 中的第一个 print 语句周围执行 tryexcept。如果还没有设置属性,也许可以跳过它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-25
  • 1970-01-01
  • 2013-07-15
  • 2015-01-15
  • 1970-01-01
相关资源
最近更新 更多