繁体   English   中英

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

[英]python inner functions treat mutable vs immutable variables differently

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

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

这是因为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时,您会再次获得该词素或符号的最后一个条目,并获取唯一的外部数组的值。

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

从python 常见问题解答

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM