【问题标题】:Nested Function Scope [duplicate]嵌套函数范围 [重复]
【发布时间】:2020-07-14 05:15:46
【问题描述】:
def foo():
  a = 0
  def bar():
    a += 1
  bar()
foo()

为什么这段代码在 a 是不可变类型时不执行,但在可变类型(例如列表)时执行?

【问题讨论】:

标签: python


【解决方案1】:

我不认为其他答案叙述了整个故事,所以这是我的 2 美分。

不同类型的范围没有区别。这不是这里发生的事情。
重新绑定名称,无论该名称指的是什么,都会导致发生未绑定的本地错误。

Python 中的某些类型是可变的(一旦创建,值就可以更改),list 就是其中之一。有些是不可变的,更改这些类型的值需要创建一个新对象。

所以,对于第一个例子,

def foo():
  a = 0
  def bar():
    a += 1
  bar()
foo()

这不起作用,因为您实际上有一个任务在这里进行,a = a + 1。您可以使用non-local 来完成上述工作,这不是重点。

对列表做同样的事情:

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

这确实有效。这里没有任务。
您不能将名称重新绑定到不同的对象,但如果对象是可变的,您可以修改其内容。

现在,还有 2 种情况您应该注意。

def foo():
  a = []
  c = []
  def bar():
    a = c + [1]
    
  bar()
  print(a)
  print(c)
foo()

这会起作用,但是您应该注意,bar() 内的 a 现在是 bar 的本地,并且 print() 语句应该反映这一点。
但这里有个问题

def foo():
  a = []
  def bar():
    a = a + [1] #or even a += [1], doesn't matter
    
  bar()
  print(a)
foo()

这行不通! (将这个 sn-p 与第一个 sn-p 进行对比很重要,因为这说明了为什么这与作用域无关。花一分钟再读一遍。)


所以这是行不通的,理解它很重要。
如果在函数内部对变量进行赋值,则该变量被视为局部变量。

现在,在最后一种情况下,当我们执行 a = c + 1 时,它更像是 a_local = c_nonlocal + 1
在这种情况下,a = a + 1a_local = a_local + 1,因此,这确实会导致错误。

这就是为什么,重新绑定一个名字,不管这个名字指的是什么,总是会导致一个未绑定的本地错误发生。
在前面的情况下(第三个sn -p),它没有重新绑定它——它正在创建一个局部变量。
在后一种情况下(第四个 sn-p),它实际上是重新绑定,因此出现错误。

【讨论】:

    【解决方案2】:

    有一个关键字nonlocal用于访问非局部变量。

    nonlocal 关键字用于处理嵌套函数中的变量,其中变量不应属于内部函数。 --w3schools.com

    def foo():
      a = 0
      def bar():
        nonlocal a
        a += 1
      bar()
    foo()
    

    谢谢

    【讨论】:

      【解决方案3】:

      那是因为您没有从任何一个函数返回任何值,而第二个 a 只是 local 到函数 bar()

      尝试像这样使用 nonlocal 关键字:

      def foo():
          a = 0
          def bar():
              nonlocal a
              a += 1
              return a
          return bar()
      print(foo())
      

      输出

      1

      【讨论】:

        猜你喜欢
        • 2011-07-10
        • 2019-08-21
        • 2021-04-03
        • 2016-09-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-14
        相关资源
        最近更新 更多