gpt4 book ai didi

Python:如何允许 ‘inner function’更改多个 ‘outer functions’中的非局部变量

转载 作者:行者123 更新时间:2023-12-01 09:32:53 25 4
gpt4 key购买 nike

假设我有一个函数,其中有大量代码在函数内的各个位置重复,我可以执行以下操作:

def foo():
def bar():
# do some stuff

bar()
# do some other stuff
bar()

我可以‘读取’foo范围内的变量在里面bar ,此外,如果我需要编辑它们,我可以这样做:

def foo():
# stuff involving var1 and var2
def bar():
nonlocal var1, var2
# do some stuff

bar()
# do some other stuff
bar()

问题

现在假设我有几个函数,foo_1 , foo_2 , foo_3 …等等,所有这些都具有来自 bar 的相同代码行在他们身上重复。定义 bar 会很单调(更不用说每次我想更改 bar 时都是一场噩梦)每个里面foo_i ,但是执行以下操作不起作用,因为它出现 nonlocal适用于定义函数的范围,而不是调用函数的范围:

def bar():
nonlocal var1, var2 # SyntaxError: no binding for nonlocal 'var1' found
# do some stuff

def foo_1():
# stuff involving var1 and var2
bar()
# do some other stuff
bar()

潜在的解决方案

解决这个问题的一种方法是传入需要更改的所有变量,然后返回它们。像这样的事情:

def bar(var1, var2):
# do some stuff
return var1, var2

def foo_1():
# stuff involving var1 and var2
var1, var2 = bar(var1, var2)
# do some other stuff
var1, var2 = bar(var1, var2)

我的问题

上面的解决方案有一些问题:

  • 它比简单的显着详细 bar() (尤其是当变量较多时)
  • 实际上,定义 bar 并没有多大改进。里面每个 foo_i因为假设我之前刚刚在 bar 内访问了一个变量我现在决定编辑。我不仅需要更改函数,而且还需要更改调用它的所有地方(因为现在我必须返回一个额外的变量)。

是否有更好的方法来实现上述目标?

(这感觉像是那种应该有答案的问题,所以如果这是一个重复的问题,我很抱歉。不过我还没有找到任何东西。)

最佳答案

[...] it appears nonlocal works on the scope in which a function is defined, not in which it is called [...].

你是对的。 nonlocal 仅适用于定义该函数的命名空间。来自 nonlocal 的文档:

The nonlocal statement causes the listed identifiers to refer to previously bound variables in the nearest enclosing scope excluding globals.

(强调我的)

正如 @Aran 提到的,避免不必要的冗长的一个潜在解决方案是将要传递的变量包装到类中的某些函数中。 namedtuple 将是一个有吸引力的选择,因为您不需要完整的类,但正如已经声明的那样,它是不可变的。您可以使用 types.SimpleNamespace相反,它们也是轻量级的:

from types import SimpleNamespace


def bar(n):
n.a = 3, n.b = 4


def foo():
n = SimpleNamespace(a=1, b=2)
bar(n)
print(n.a, n.b) # 3 4

关于Python:如何允许 ‘inner function’更改多个 ‘outer functions’中的非局部变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49803462/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com