只在一个函数中重用代码的Pythonic方法

只在一个函数中重用代码的Pythonic方法,python,dry,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:

我的问题是指在函数中多次需要组织代码,而不是在其他地方

假设以下用例:

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

    # ...
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

    # ...
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

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

但是:它无法测试,嵌套函数无法从外部访问以进行单元测试。我真的不想把它作为
foo()
的一部分进行测试,因为它需要测试所有
加上两次
(对于这两种if情况)。在单元测试中,应该可以分别测试
和两个
,并且只能在
foo()
中正确调用它

(2.辅助方法

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

    # ...
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

    # ...
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

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

(3.)模块功能:

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

    # ...
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

    # ...
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

    # ...
但是:这会导致几个助手函数脱离其特定上下文,换句话说,不遵循封装。虽然这似乎不是一个问题,也可能是一个解决方案,但在我的项目中,这确实会使整个模块变得混乱,因为函数通常与模块无关,但正如前面所说的,非常特定于它所使用的方法。换句话说:将其拆分到远离其上下文的某个地方,会使代码的可读性和Python性大大降低


还有其他方法吗,或者我应该从这里显示的三种方法中选择一种吗?

我当然希望实际示例更复杂:)

我要说的是使用嵌套函数或辅助函数。我个人倾向于使用helper函数,但这只是我的观点。
这当然是从我对你的描述中可以看出的。实际的代码将为建议提供更好的依据,而不仅仅是一个随机示例

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

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

我真的不想把它作为foo()的一部分来测试


然后,您需要使用选项2的一些变体。理想的私有方法将是此行的方法,但由于Python不支持它,至少考虑命名它<代码>α-PulsSouthTo()\代码>这是一个有关Python中的领先双下划线的相关问题:这里是与私有方法相关的另一个问题:

进一步考虑您的建议,代替实例方法,你认为一个与实例或类无关,而与“类相关的东西”相关的
静态方法更合适吗?(好吧,它仍然会被放在一个比它需要的更广泛的环境中,但至少不会是一个模块函数。)静态下划线方法是最好的选择吗?我们没有所有真实情况的背景来知道将函数设为静态是否有意义。通常,静态函数执行与类相关的某种功能,而不需要类的实例,这里的情况似乎不是这样。我认为这里最好使用双下划线,并对函数进行注释,说明其用途。