繁体   English   中英

定义在初始化时按顺序计算属性的类的最佳实践

[英]Best practice for defining a class that computes attributes in order when initialized

我想定义一个执行以下操作的类:

Class computer():
    def __init__(self, x):
        # compute first the 'helper' properties
        self.prop1 = self.compute_prop1(x)
        self.prop2 = self.compute_prop2(x)
        # then compute the property that depends on 'helpers'
        self.prop3 = self.compute_prop3(x)

    def compute_prop1(self, x):
        return x
    def compute_prop2(self, x):
        return x*x
    def compute_prop3(self, x):
        return self.prop1 + self.prop2

然后,当我初始化一个实例时,我会按顺序计算所有属性(首先是助手,然后是一切取决于助手):

>>> computer = Computer(3)
>>> computer.__dict__
{'prop1': 3, 'prop2': 9, 'prop3': 12}

但是,我认为编写此代码有更好的做法,例如使用装饰器。 你能给我一些提示吗? 谢谢!

这是您使用属性的类(添加了用于返回每个属性的方法):

Class PropertyComputer:
    def __init__(self, x):
        self._x = x

    @property
    def prop1(self):
        return self._x

    @property
    def prop2(self):
        return self._x * self._x

    @property
    def prop3(self):
        return self.prop1 + self.prop2

    def get_props(self):
        return self.prop1, self.prop2, self.prop3

在设计方面,我相信这更好,因为:

  • x存储为实例变量更有意义:使用对象的目的是避免必须传递变量,尤其是那些对象本身可以跟踪的变量;
  • 属性赋值及其相应的计算捆绑在每个属性修饰的方法中:我们永远不必考虑问题是在 init 方法(定义属性的地方)还是计算方法(其中的逻辑)属性的计算被列出)。

请注意,“首先计算帮助程序,然后根据它们计算属性”的概念并不真正适用于此代码:我们只需要在实际需要时评估prop3 如果我们从不访问它,我们就永远不需要计算它。

与您的示例相比,使用属性的“坏”副作用是这些属性不会“存储”在任何地方(因此我添加了最后一个方法):

c = PropertyComputer(x=2)
c.__dict__  # outputs {'_x': 2}

另请注意,使用装饰器,属性在您访问它们时即时计算,而不是在 init 方法中仅计算一次。 以这种方式,属性修饰的方法像方法一样工作,但像属性一样访问(这是使用它们的全部意义):

c = PropertyComputer(x=2)
c.prop1  # outputs 2
c._x = 10
c.prop1  # outputs 10

作为旁注,您可以使用functools.cached_property来缓存对这些属性之一的评估,以防计算成本很高。

我认为以下是避免冗余的最简单方法

class computer():
    def __init__(self, x):
        self.prop_dict = self.compute_prop_dict(x)

    def compute_prop_dict(self, x):
        prop1 = x
        prop2 = x*x
        return {'prop1': prop1, 'prop2': prop2, 'prop3': prop1 + prop2}

因此,实例化后的任何内容都可以通过prop_dict访问这些助手

但正如 Brian 在评论中所说,这个命令只是 Python 3.7 的语言规范

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM