一个实例属性引用另一个实例属性,在 class 实例化后进行更新

One instance attribute referencing another, with updates after class instantiation

我正在寻找在实例化 class 之后设置引用另一个实例属性的实例属性的最佳实践。

例如:

class Foo:
    def __init__(self):
        self.a = 1
        self.b = self.a + 1
>>> obj_foo = Foo()
>>> obj_foo.a
1
>>> obj_foo.b
2
>>> obj_foo.a = 5
>>> obj_foo.a
5
>>> obj_foo.b
2 # I want this to be 6

一个实例属性引用另一个实例属性是一种不好的做法吗?

我可以看到如何实现检查和更新依赖实例属性的方法,但这似乎很多 overhead/hacky。非常感谢任何帮助!

您似乎根本不想存储 b 的值,而是想根据 a 的值动态生成它。幸运的是,有一个 property class/decorator 可以用于此目的:

class Foo:
    def __init__(self, a=1):
        self.a = a

    @property
    def b(self):
        return self.a + 1

这将创建一个只读的 属性 b,当您以 foo.b 访问它时,它的行为就像普通属性一样,但会因为它是 descriptor。它将根据 foo.a 设置的值重新计算值。

您担心每次都调用方法进行计算并非完全没有道理。使用 . 运算符已经执行了一些相当昂贵的查找,因此您的玩具箱没有问题,如上所示。但是您经常会 运行 遇到需要更多东西的情况,而不仅仅是在参数上加 1。在这种情况下,您需要使用缓存之类的东西来加快速度。例如,您可以将 a 设置为可设置的 属性。每当更新 a 的值时,您都可以 "invalidate" b 以某种方式设置标志,或者只是将 None 分配给缓存值。现在,您的昂贵计算仅在必要时 运行s:

class Foo:
    def __init__(self, a=1):
        self._a = a

    @property
    def a(self):
        return self._a

    @a.setter
    def a(self, value):
        self._a = value
        self._b = None

    @property
    def b(self):
        if self._b is None:
            # Placeholder for expensive computation here
            self._b = self._a + 1
        return self._b

在此示例中,在 __init__ 中设置 self.a = a 将触发 属性 foo.a 的 setter,确保属性 foo._b 一直存在。