【问题标题】:Python: How to automatically change an attribute of an instance depending on the boolean value of another attribute of the same instance?Python:如何根据同一实例的另一个属性的布尔值自动更改实例的属性?
【发布时间】:2020-10-23 11:07:51
【问题描述】:

假设我有这个类和它的一个实例

class MyClass:
    a = False
    b = [0,1,2]

MCi = MyClass()

显然MCi.a 提供FalseMCi.b 提供[0,1,2]

如果我设置MCi.a = True,我想要的是MCi.b 的值更改为[0,1,2,3,4,5]。当我退回MCi.a = False时,我希望它回到[0,1,2]

换句话说,MCi.a 应该指示MCi.b,而不必从外部设置后一个属性值。

我该怎么做?

这个问题与我之前问过的this one 非常接近,但是我没有足够仔细地表达我的问题,所以那里提供的解决方案实际上并不是我需要的。不过,使用__setattr__() 的想法可能是一个好的开始。但到目前为止我失败了。

【问题讨论】:

  • 你试过@property装饰器
  • @Britzel,我点击了您之前问题的链接。我仍然对一件事感到有些困惑——您希望ab 成为instance 属性还是class 属性?希望您知道其中的区别。
  • 嗨@fountainhead!当我问这个问题时,我还没有意识到差异。现在我想我是:一个类属性改变了类中变量的值,即在蓝图中创建实例。所以每个新实例都会有新值,而每个旧实例都会保留旧值。实例属性的更改使蓝图保持不变,但它仅更改特定实例的值的值。对吗?
  • @fountainhead 如果是这样,那么我认为我需要的是一个实例属性。我还不是 100% 确定,因为我还没有在我的实际代码中测试它。我在这里发布的是,我认为这是一个展示我需要的最小示例。但周一回到办公室还有待观察。 ; )

标签: python python-3.x object attributes instance


【解决方案1】:

在这种情况下,我会使用一种方法来设置布尔值。这样您就永远不会直接从外部设置布尔实例变量,而是调用一个方法来更改它。如果你想隐藏,实际上使用了一个方法,你可以将它定义为一个属性。这看起来像:

class MyClass:
    # prefix the instance variables with an underscore
    # as a convention to indicate they are private
    _a = False
    _b = [0,1,2]

    # define accessors
    @property
    def a(self):
        return self._a

    @a.setter
    def a(self, bool):
        self._a= bool
        if bool is True:
            self._b= [0,1,2,3,4,5]
        else:
            self._b= [0,1,2]

    # define accessors
    @property
    def b(self):
        return self._b

现在我们可以测试一下:

o= MyClass()
print(f'{o._a}, {o._b}')
o.a=True
print(f'{o._a}, {o._b}')
o.a=False
print(f'{o._a}, {o._b}')
print(o.b)
o.b=[12,3]

打印出来:

False, [0, 1, 2]
True, [0, 1, 2, 3, 4, 5]
False, [0, 1, 2]
[0, 1, 2]
Traceback (most recent call last):

  File "<ipython-input-14-1e243ad0d3ed>", line 8, in <module>
    o.b=[12,3]

AttributeError: can't set attribute

所以你可以看到,_b 的内容确实发生了变化,当通过o.a= 分配一个布尔值时,你也可以使用属性o._b 访问o._b 的值o.b,但是你无法通过o.b= 进行设置。这只是因为我没有定义setter。如果您想拥有一个,则必须为其定义一个函数,就像在a 的设置器中一样。

如果您以这种方式定义它,您应该遵循约定,即您不能在代码中的类MyClass 之外的任何地方访问真实的实例变量_a_b

【讨论】:

  • 嗨@jottbe,非常感谢!现在这正是我需要的。您能否帮助我理解:我不知道@ 的这种表示法。我试图删除这些行,但它不起作用,所以它似乎很重要。这些是什么意思/做什么?
  • 哦,我找到了一个很好的来源来解释它。它是一种特殊的装饰器。
  • 你好,它叫装饰器。没有它,您将只有一种方法a btw。因为def a(self, bool) 行只会覆盖定义def a(self)
猜你喜欢
  • 2023-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多