python内部函数以不同方式对待可变变量和不可变变量

时间:2018-10-22 01:30:30

标签: python

我试图理解为什么内部函数可以访问外部列表(arr)但不能访问外部布尔变量(找到)。

def outer():
    arr = [1, 2, 3]
    found = False
    print("outer func ids: ", id(arr), id(found))
    def inner(num):
        arr.append(4)
        found = True
        print("inner func ids:", id(arr), id(found))
    inner(3)
    print("outer func ids: ", id(arr), id(found))
    return found
outer()

输出:

('outer func ids: ', 4536180248, 140736008926072)
('inner func ids:', 4536180248, 140736008926048)
('outer func ids: ', 4536180248, 140736008926072)

有人可以澄清一下吗?即使我们在内部函数中执行追加操作,为什么列表具有相同的ID?

3 个答案:

答案 0 :(得分:1)

因为在found中重新定义inner使其成为本地的。与可变无关。

答案 1 :(得分:0)

这是因为Python使用静态范围/是静态范围的。在实现级别,Python具有所谓的符号表,其中包含用于在代码中定义的事物(例如变量和函数)的条目。

这些事物中的每一个都由一个词素表示,并具有“值”和“范围”之类的属性。

例如,对于第一个发现的对象,您具有:

LEXEME |  VALUE | SCOPE

found  |  False |  outer

定义第二个发现项时,将为该发现项生成一个范围为“内部”的条目。因此,在执行print("inner func ids:", id(arr), id(found))的那一刻,Python在Symbol Table中搜索了一个“ found”条目,并使用了最新的条目(具有内部作用域的条目)。像这样:

LEXEME |  VALUE | SCOPE

found  |  False |  outer
found  |  True  |  inner

该数组只是唯一的,因此当搜索该arr时,您会再次获得该词素或符号的最后一个条目,并获取唯一的外部数组的值。

这不是可变或不变的,而是范围。

答案 2 :(得分:0)

来自python Faq

Python,仅在函数内部引用的变量是隐式全局的。如果在函数体内任何位置为变量分配了值,除非明确声明为全局变量,否则假定该变量为局部变量。

尽管起初有些令人惊讶,但片刻的考虑解释了这一点。一方面,要求全局分配变量可防止意外副作用。另一方面,如果所有全局引用都需要全局,那么您将一直使用全局。您必须将对内置函数或导入模块的组件的所有引用声明为全局引用。这种混乱将破坏全球宣言对确定副作用的有用性。

尝试found赋值并查看其ID。

让我们看一些示例:

a = [1, 2, 3]
b = True
c = 123
d = "Hello"

def print_global1():
  print("print_global1: a=", a, id(a))
  print("print_global1: b=", b, id(b))
  print("print_global1: c=", c, id(c))
  print("print_global1: d=", d, id(d))

def print_global2():
  global a, b, c, d
  print("print_global2: a=", a, id(a))
  print("print_global2: b=", b, id(b))
  print("print_global2: c=", c, id(c))
  print("print_global2: d=", d, id(d))

def print_global3():
  global a, b, c, d
  a.append(4)
  b = False
  c += 1
  d = d.upper()
  print("print_global3: a=", a, id(a))
  print("print_global3: b=", b, id(b))
  print("print_global3: c=", c, id(c))
  print("print_global3: d=", d, id(d))

print("a=", a, id(a))
print("b=", b, id(b))
print("c=", c, id(c))
print("c=", d, id(c))
print("")
print_global1()
print("")
print_global2()
print("")
print_global3()

输出为:

a= [1, 2, 3] 3206482320648
b= True 1625616544
c= 123 1626110848
c= Hello 1626110848

print_global1: a= [1, 2, 3] 3206482320648
print_global1: b= True 1625616544
print_global1: c= 123 1626110848
print_global1: d= Hello 3206481522616

print_global2: a= [1, 2, 3] 3206482320648
print_global2: b= True 1625616544
print_global2: c= 123 1626110848
print_global2: d= Hello 3206481522616

print_global3: a= [1, 2, 3, 4] 3206482320648
print_global3: b= False 1625616576
print_global3: c= 124 1626110880
print_global3: d= HELLO 3206482331664