我试图理解为什么内部函数可以访问外部列表(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?
答案 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