Python 辅助函数作用域

Python helper function scope

所以,我有一大堆东西在做基本相同的事情,只是输入稍有变化。完美的候选人,每次都使用不同的参数进行功能和调用,对吧?

显然,python 认为我错了。

所以,这是我的问题的简化版本

def main():
    x = 10

    def helper(n):
      if (x > n):
          x -= n

helper 函数中还有几十行其他代码,它在 main 中被调用了几十次,但正是这些行导致了我的问题。我知道 helper 函数使用局部范围而不是使用 main 中的范围,但我的问题是,为什么?我该如何解决?

我不想让 x 全局化,我只是想让助手使用已经存在的 x 而不是自己构建。如果没有这个辅助函数,代码的总行数至少会翻两番,而且代码会很复杂,不可读。

编辑:另外,Main 使用了一大堆 x,所以我不能只在本地定义它,以防万一不清楚。

在 Python 3 中,您可以通过将 nonlocal x 放在内部函数中来实现。在 Python 2 你做不到。

但是,您可以做的是 return 辅助函数的值,并在您调用辅助函数的地方分配它。从你的例子中很难看出,但我假设你正在使用它:

def main():
    x = 10

    def helper(n):
        if (x > n):
            x -= n

    # do something that changes x
    helper(2)
    # now x has changed

相反,这样做:

def helper(x, n):
    if (x > n):
        return x - n
    else:
        return x

def main():
    x = 10

    # do something that changes x
    x = helper(x, 2)
    # now x has changed

我们的想法是向辅助函数传递它需要的值,并让它 return 结果值,然后你可以在辅助函数所在的地方分配(或做你喜欢的事情)叫。这通常也使代码更易于理解,而不是让辅助函数直接修改其调用者中的变量。另请注意,您可以在此处在 main 之外定义 helper,从而在两者之间创建更清晰的分隔,并使 helper 可用于其他函数。

问题在线:x -= n。由于您正在进行扩充赋值,因此 python 认为(错误地) x 是局部变量。不幸的是,x 是一个 "nonlocal" 变量。在 python3.x 上,如果您可以在 main 范围内修改 x,那么您可以使用 nonlocal 关键字。但是,我猜您不想在 main 的范围内修改 x。一个跨版本的技巧是让自己得到一个与非本地版本具有相同值的局部变量:

def main():
    x = 10
    def helper(n):
        lx = x
        if x > n:
           lx -= n
        # etc., etc.

    helper(12)  # ...

如果你真的想在 main 的范围内改变 x,你可能需要考虑 class(helper class):

class Main(object):  # Main for lack of a better name...
    def __init__(self, x):
        self.x = x
    def helper(self, n):
        if self.x > n:
            self.x -= n

def main():
    x = Main(10)
    ...
    x.helper(12)
    ...