在Python中,状态对象与无状态计算的分界在哪里?

1 投票
5 回答
1676 浏览
提问于 2025-04-15 20:12

以下哪个代码片段是最“符合Python风格”的?虽然在这个例子中计算很简单,但在实际生活中可能会很复杂。

class A(object):
    """Freely mix state and calcs - no good I presume"""
    def __init__(self, state):
        self.state = state

    def calc_with_state(self, x):
        return (self.state + x)**2

或者

class B(object):
    """Separate state from calc by a static method"""
    @staticmethod
    def inner_calc(u, v):
        return (u + v)**2

    def __init__(self, state):
        self.state = state

    def calc_with_state(self, x):
        return B.inner_calc(self.state, x)

或者

class C(object):
    """Break out the calculation in a free function"""
    def __init__(self, state):
        self.state = state

    def calc_with_state(self, x):
        return outer_calc(self.state, x)

def outer_calc(u, v):
    return (u + v)**2

5 个回答

1

把计算过程单独提出来,无论是用静态方法还是全局方法,其实对“状态意识”没有什么好处。唯一稍微有点好处的是,代码能清楚地显示出在计算中考虑了哪些对象的状态属性(这样在调用函数的时候就能看到,而不需要在类A的方法逻辑里去找)。

不过,使用无状态的方法(静态的、全局的)或者实例方法可能还有其他一些好处:

  • 可以重复使用
  • 整体上代码更易读和管理

但是,正如前面所说,这些方法对状态管理本身并没有帮助。我觉得A的方法看起来很合理(而且符合Python的风格)。确实,David Berger 早就提醒过我们……

简单比复杂好!

1

我觉得这要看你具体的项目情况。cal_with_state这个方法是只适用于这个特定的类,还是说这个方法需要在很多不同的对象之间共享?不同的类之间会共享这个方法吗?

这些方法没有哪个更“pythonic”(符合Python风格)的说法,选择一个能满足你项目需求的方法就好。DRY(不要重复自己)是比“pythonic”更重要的原则。

6

简单来说,答案是A,差得远。问题很简单,就是:

简单比复杂好。

你看:把状态和计算分开是个好设计原则,但这并不意味着你想的那样,至少不是我从这个例子中能推测到的。我们要确保状态在进行计算时不会发生变化,前提是这个状态在下一次计算时不会被重新初始化。如果某个计算对状态是只读的,那么就没有必要绕过它,直接去读取它。也就是说,除非计算和状态复杂到需要单独进行单元测试。这样的话,B或C会更受欢迎,但前提是创建u的值真的比重新实例化的实例要简单得多。

撰写回答