【发布时间】:2014-11-13 11:10:42
【问题描述】:
我正在编写一些使用类作为有限元模型元素的数字代码。 我很欣赏将一组参数传递给函数并传递一个结果的函数式编码风格,但我想知道将这种风格与类和方法一起使用是否有点过分。我在显示我的数字根吗?
我想知道:
- 将参数传递给方法的惯用方式是什么?
- 如果我想明确数据流,在离开 pythonic 好品味的领域之前,我还能走多远?
例如,我有以下三个类:
StandardPoint 代表我认为是常见的 Python 代码,但它隐式传递状态,使代码不太清晰,更难测试。不过,它看起来确实很整洁。
ExplicitPoint 使状态的突变更加明确,可能是我的首选。这不太整洁,并且仍然隐式地将状态传递给方法。我认为单元测试仍然需要模拟对象。
ExtremePoint 使所有数据传递显式化,但更高级别的代码当然更嘈杂(一行中有四个 self)。对方法进行单元测试变得非常容易。静态方法几乎可以肯定是一步过头了,但因为你不需要 self 作为状态是有意义的。顶层函数更 Pythonic(我建议),但前提是不止一个类需要它。
from math import sqrt
class StandardPoint(object):
"""Is this idiomatic python?"""
def __init__(self, x, y):
self.x = x
self.y = y
self._calc_distance()
def _calc_distance(self):
self.distance = sqrt(self.x**2 + self.y**2)
class ExplicitPoint(object):
"""Explicit setting of attributes but implicit passing-in of data."""
def __init__(self, x, y):
self.x = x
self.y = y
self.distance = None
# ...
self.distance = self._calc_distance()
def _calc_distance(self):
return sqrt(self.x**2 + self.y**2)
class ExtremePoint(object):
"""Explicit data passing everywhere."""
def __init__(self, x, y):
self.x = x
self.y = y
self.distance = None
self.distance = self._calc_distance(self.x, self.y)
# or even
# self.distance = self._calc_distance_static(self.x, self.y)
def _calc_distance(self, x, y):
return sqrt(x**2 + y**2)
@staticmethod
def _calc_distance_static(x, y):
return sqrt(x**2 + y**2)
def calc_distance(x, y):
"""Top-level function for use by many classes."""
return sqrt(x**2 + y**2)
【问题讨论】:
-
StandardPoint和ExplicitPoint是相同的......它不像你正在预热变量或其他东西。ExplicitPoint是减少对象状态的正常方式。回到前两个例子,不要在 init 上计算……你可以用@property装饰器让它变得漂亮,或者你可以记住它(记住 x、y 和最后一次计算的结果)。您甚至可以为 x 和 y 编写设置器,以便在其中一个更改时在后台重新计算。我已经在 GUI 应用程序中完成了这个,我希望结果动态改变。
标签: python unit-testing