【问题标题】:Are explicit method arguments a good idea? - Idiomatic Python显式方法参数是个好主意吗? - 惯用的 Python
【发布时间】:2014-11-13 11:10:42
【问题描述】:

我正在编写一些使用类作为有限元模型元素的数字代码。 我很欣赏将一组参数传递给函数并传递一个结果的函数式编码风格,但我想知道将这种风格与类和方法一起使用是否有点过分。我在显示我的数字根吗?

我想知道:

  1. 将参数传递给方法的惯用方式是什么?
  2. 如果我想明确数据流,在离开 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)

【问题讨论】:

  • StandardPointExplicitPoint 是相同的......它不像你正在预热变量或其他东西。 ExplicitPoint 是减少对象状态的正常方式。回到前两个例子,不要在 init 上计算……你可以用 @property 装饰器让它变得漂亮,或者你可以记住它(记住 x、y 和最后一次计算的结果)。您甚至可以为 x 和 y 编写设置器,以便在其中一个更改时在后台重新计算。我已经在 GUI 应用程序中完成了这个,我希望结果动态改变。

标签: python unit-testing


【解决方案1】:

最自然的方法是:

class TestClass(object):

    def __init__(self, x, y):
        self.x = x
        self.y = y

    @property
    def distance(self):
        return sqrt(self.x**2 + self.y**2)

将实例变量传递给方法很奇怪,也没有必要。

您的所有示例都会产生一个问题,即如果 xy 发生变化,那么 distance 将不正确,除非开发人员也记得更新它。您想即时计算distance

【讨论】:

    猜你喜欢
    • 2011-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-15
    • 1970-01-01
    • 2019-02-19
    • 2016-12-19
    • 2012-10-16
    相关资源
    最近更新 更多