在Python中,是否有可能修改一个位于外部(封闭)而非全局作用域中的变量?

14 浏览
0 Comments

在Python中,是否有可能修改一个位于外部(封闭)而非全局作用域中的变量?

考虑下面的例子:

def A():
    b = 1
    def B():
        # 我可以在这里访问'b'。
        print(b)
        # 但我可以在这里修改'b'吗?
    B()
A()

对于B函数中的代码,变量b处于一个非全局的封闭(外部)作用域。我如何在B中修改b?如果我直接尝试,会出现UnboundLocalError错误,并且使用global也无法解决问题,因为b不是全局的。


Python 实现的是词法作用域,而不是动态作用域 - 就像几乎所有现代语言一样。这里的技巧不会允许访问调用者的变量 - 除非调用者也恰好是封闭函数 - 因为调用者不在作用域内。有关这个问题的更多信息,请参见How can I access variables from the caller, even if it isn't an enclosing scope (i.e., implement dynamic scoping)?

0
0 Comments

在Python中,如果想要修改一个处于外部(包围)但不是全局范围的变量,可以使用nonlocal关键字。这是因为默认情况下,变量的绑定会先在局部命名空间中进行搜索。而nonlocal语句允许封装的代码重新绑定局部作用域之外的变量,除了全局(模块)作用域。

在Python 3中,可以使用nonlocal关键字来实现这一点。如下例所示:

def foo():
    a = 1
    def bar():
        nonlocal a
        a = 2
    bar()
    print(a)  # 输出: 2

在Python 2中,可以使用可变对象(如列表或字典)并对值进行修改,而不是重新分配变量。如下例所示:

def foo():
    a = []
    def bar():
        a.append(1)
    bar()
    bar()
    print a
foo()

输出:

[1, 1]

另一种方法是在外部作用域中使用`class nonlocal: pass`,然后在内部作用域中可以对`nonlocal.x`进行赋值。

这种行为的逻辑是:在Python中,`a = 2`语句是有歧义的,因为它既用于声明新变量,也用于修改现有变量(例如,与Scheme进行比较,Scheme有单独的`let`和`set!`)。Python 2无法区分所需的含义,因此默认假定需要一个新变量。Python 3默认采用相同的行为,但允许使用`nonlocal`关键字来使用另一种行为。

更多关于这个的问题和示例代码可以参考这个链接:stackoverflow.com/questions/1261875

0
0 Comments

在Python中,有时候我们希望在内部函数中修改外部(封闭)作用域中的变量,但不是全局作用域中的变量。然而,Python的作用域规则并不允许直接修改外部作用域中的变量。为了解决这个问题,我们可以使用一个空的类来临时存储变量,从而创建一个临时作用域。这个方法使得代码更加优雅。

首先,我们定义一个外部函数outer_fn(),其中包含一个内部函数inner_fn()。为了创建一个临时作用域,我们在outer_fn()中定义了一个空的类FnScope,里面包含了变量b和c。

接下来,在inner_fn()中,我们可以通过使用FnScope来访问和修改临时作用域中的变量。在这个例子中,我们通过FnScope.b += 1来修改变量b的值,并通过FnScope.c += FnScope.b来修改变量c的值。在outer_fn()中,我们连续三次调用了inner_fn(),以便看到变量的修改效果。

当我们运行outer_fn()时,会得到如下的输出结果:8 27。这表明变量b被成功地修改为8,并且变量c也被相应地修改为27。

然而,如果我们尝试在外部作用域中访问FnScope,会得到一个NameError的错误提示,因为FnScope只在inner_fn()中可见,而不在外部作用域中可见。

为了解决这个问题,我们可以使用"nonlocal"关键字来定义外部变量。这样,我们就可以在inner_fn()中访问和修改外部作用域中的变量。另外,我们还可以通过在外部作用域中初始化一个字典,并在内部函数中设置字典的键来实现类似的效果。

总结起来,要在Python中修改外部作用域中的变量,我们可以使用一个临时的类来创建一个临时作用域,并通过"nonlocal"关键字或者设置字典的键来访问和修改外部作用域中的变量。这样,我们就可以在内部函数中修改外部作用域中的变量,从而解决了这个问题。

0
0 Comments

问题的出现原因是在Python中,内部函数无法直接修改外部(包围)作用域中的变量。这是因为在Python中,变量的作用域是基于函数的,每个函数都有自己的作用域。

解决方法是将外部变量包装在一个列表中。通过将外部变量赋值给列表的元素,内部函数可以修改列表的元素值,从而实现修改外部变量的效果。

以下是一个示例代码:

def A():
   b = [1]
   def B():
      b[0] = 2
   B()
   print(b[0])
# 输出结果为 '2'

不过,从Python 3开始,引入了nonlocal关键字,可以直接修改外部变量。在Python 3.9及更高版本中,可以使用nonlocal关键字来实现修改外部变量的效果。

0