Pythonic方法只在一个函数内部重用代码

时间:2013-06-05 09:55:15

标签: python dry

我的问题是指在函数内部多次组织代码,而不是其他任何地方。

假设以下用例:

class A(object):
    def __init__(self, base):
        self.base = base

    def foo(self):
        result = self.base + 2    # Should go to an extra function.
        result = result * 4
        if result > 10:
            result = result + 2   # Should go to an extra function.
        return result

    def bar(self):
        pass

foo()中有x + 2部分重复,在我的项目中有20行代码(将值添加到另一个对象的20个属性),应该被抽象。但是把它放在哪里?我认为有三种方法可以做到:

(1。)嵌套函数

class A(object):
    # ...

    def foo(self):
        def plus_two(value):
            return value + 2

        result = plus_two(self.base)
        result = result * 4
        if result > 10:
            result = plus_two(result)
        return result

    # ...

这似乎有意义,因为它是非常特定的用例,只与方法内部发生的事情有关。

但是:无法测试,无法从外部访问嵌套函数进行单元测试。我真的不想将此作为foo()部分进行测试,因为它需要两次测试{em>所有 plus_two如果情况)。在单元测试中,应该可以单独测试plus_two,并且只能在foo()中测试其正确的调用

(2。)辅助方法

class A(object):
    # ...

    def foo(self):
        result = self.plus_two(self.base)
        result = result * 4
        if result > 10:
            result = self.plus_two(result)
        return result

    def plus_two(self, value):
        return value + 2

    # ...

但是:该方法是并且永远不会被类中的任何其他方法使用,也不需要访问self,因此它不应该成为该类的方法。在不需要访问对象的类中收集函数或者不需要将其作为接口的一部分覆盖它不是pythonic。

(3。)模块功能

def plus_two(value):
    return value + 2

class A(object):
    # ...

    def foo(self):
        result = plus_two(self.base)
        result = result * 4
        if result > 10:
            result = plus_two(result)
        return result

    # ...

但是:这导致几个辅助函数从其特定的上下文中取出,换句话说,不遵循封装。虽然这似乎不是一个问题,并且可能看起来是解决方案,但在我的项目中,这确实会使整个模块变得混乱,因为该功能通常与模块无关,但正如所说,非常具体使用它的方法。换句话说:将它拆分到远离其上下文的某个地方,它使代码可读性更低,并且更少pythonic。

还有其他方式,还是应该选择此处显示的三种方式之一?

2 个答案:

答案 0 :(得分:0)

我当然希望真正的例子更复杂:)

我想去嵌套或帮助函数。我个人会去帮助函数,但这只是我的意见。 这当然来自我所说的你的描述。实际代码将为建议提供更好的基础,而不仅仅是一个随机的例子。

答案 1 :(得分:0)

就个人而言,我认为选项1或2都是最干净的。正如你所提到的,选项3是特定于上下文的,被定义为模块函数。

要在选项1或2之间做出决定,您需要决定能够对该特定代码进行单元测试的重要性。考虑到你已基本回答了单元测试重要性的问题,以及它是否可以在foo()中进行单元测试,

  

我真的不想将此作为foo()

的一部分进行测试

然后你需要选择一些选项2的变体。理想情况下私有方法将是这里的方法,但由于python不支持,至少考虑命名它__plus_two()这是一个相关的问题关于Python中的前导双下划线:What is the meaning of a single- and a double-underscore before an object name?这是与私有方法相关的另一个问题:Why are Python's 'private' methods not actually private?