Which of the following code snippets is the most “pythonic”? The calculation is trivial in this example but could be assumed to be complex in real life.
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
or
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)
or
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
As written, A, by a longshot. The issue, quite simply, is
Look: separating state from calculations is a good design principle, but it doesn’t mean what you think, at least not what I can infer you think from this example. We want to make sure that state doesn’t change in order to complete calculations if that state isn’t going to be reinitialized on the next calculation. If state is read-only with respect to some particular calculation, there’s no stylistic compulsion to redirect around it so that you don’t directly read it. That is, unless the calculation and the state are sufficiently complex to need separate unit testing. Then, by all means, B or C will be preferred, but only if it is really that much easier to create values for
uthan to instantiate fresh instances ofA.