【问题标题】:Best practices python classes最佳实践 python 类
【发布时间】:2017-09-07 14:24:41
【问题描述】:

我有一些看起来很像的代码

class Foo:
    def __init__(self, a, b, c=None):
        self.bar = a
        if c:
            self.data = self.calc(b, c)
    def calc(self, bat, baz):
        """calculates some stuff that feels like should belong with the instance of `Foo`"""
  1. 在我的__init__ 中有代码不好吗?

  2. 如果我有一个方法可以生成与类实例相关的一些数据,让用户调用该方法并存储数据是更好的做法,还是让其中一个实例变量在实例化时存储它?

2 的原因是因为我有这个类,其中所有内容都可以从某个 json 文件生成,所以该类应该只有一个实例变量和一堆方法吗?这甚至不应该是一堂课吗?我一直认为具有一个实例变量的类是不好的做法,但另一方面,我有一组函数都在同一个 json 文件上运行,所以它们感觉它们应该属于某个联合结构。

编辑:作为第三个问题,与 2 相关,如果某些方法需要依赖于初始化数据、计算数据的数据,该怎么办。所以在上面的例子中,假设我(用户)计算d=2*a+b,因为它是我感兴趣的。然后我想做另一个计算,如果我给它d,理论上会加速。所以一个看起来像new_calc(self, d) 的方法。我应该在最初计算时将d 存储在类中,然后不向用户询问,还是应该让他们更负责任?

【问题讨论】:

  • 只有一点:如果c 为None,您应该将self.data 设置为合理的默认值。另请注意,对于(至少)空列表、空元组、空集、空字典、空字符串和数字零(整数、浮点数或小数),bool(c) 可能会评估为 False
  • @brunodesthuilliers 当然是对的。我可能做了一个不是很好的 MWE……哎呀
  • 另外,如果您使用的是 Python 2.x,您希望从 object 继承以获得一个“新式”类,该类将正确支持计算属性和 super() 调用。跨度>
  • 我记得在某处读到过,好的 OO 设计旨在最大限度地减少外部代码对方法排序/依赖的需求——即 记得在调用 g() 之前调用 f() .取决于计算成本和可能最终需要 d,当然为什么不 @init。另一方面,property w 缓存也可以工作。

标签: python class oop


【解决方案1】:

在我的 init 中有代码是不是很糟糕?

没有。但是如果它做任何复杂的事情,把代码分解成一个函数/方法,就像你对 calc 所做的那样。只有我建议您使用 _calc 而不是 calc 如果该方法的唯一调用者是构造函数。这样一来,您就可以向班级用户发出信号,他们不打算自己打电话给_calc

挑剔:

if c:
   self.data = self.calc(b, c)

我会警惕这段代码,因为如果 c 为 None(或 0,或 False), self.data 仍未设置。所以你所有其他的方法都必须 检查data 属性是否存在。写起来可能更好

self.data = self.calc(b, c) if c is None else None

或者您可以将 None 的检查移到 calc 方法中,并在构造函数中显示该行

self.data = self.calc(b, c)

让用户调用该方法是否更好

我认为这取决于具体的用例。如果每个实例代表一个特定的数据集,并且不需要将一组数据换成另一组数据,我会说构造函数这样做更有意义。这样,数据就被实例很好地封装了,用户不会在不应该改变的时候改变数据而犯下愚蠢的错误。

【讨论】:

  • 对,将calc 设为私有,是的,正如@brunodesthuilliers 指出的那样,self.dat 无论如何都应该设置为某个值。谢谢你的回答!
猜你喜欢
  • 2014-03-02
  • 2013-11-12
  • 1970-01-01
  • 2018-01-31
  • 2011-04-25
  • 2013-11-08
  • 1970-01-01
  • 1970-01-01
  • 2011-07-11
相关资源
最近更新 更多