Python 在函数中调用局部变量()不直观?

Python 在函数中调用局部变量()不直观?,python,locals,Python,Locals,这可能是最基本的,但可以帮助我理解名称空间。 一个好的解释可能会解释当 函数定义被执行,然后会发生什么 当函数对象被执行时。 递归可能会使事情复杂化 结果对我来说并不明显;我原以为: In [1]: def func(): ...: var = 'var!' ...: locals1 = locals().copy() ...: locals2 = locals().copy() ...: locals3 = locals().copy()

这可能是最基本的,但可以帮助我理解名称空间。 一个好的解释可能会解释当 函数定义被执行,然后会发生什么 当函数对象被执行时。 递归可能会使事情复杂化

结果对我来说并不明显;我原以为:

In [1]: def func():
   ...:     var = 'var!'
   ...:     locals1 = locals().copy()
   ...:     locals2 = locals().copy()
   ...:     locals3 = locals().copy()
   ...:     return locals1, locals2, locals3
   ...:

In [2]: locals1, locals2, locals3 = func()

In [3]: locals1
Out[3]: {'var': 'var!'}

In [4]: locals2
Out[4]: {'locals1': {'var': 'var!'}, 'var': 'var!'}

In [5]: locals3
Out[5]:
{'locals1': {'var': 'var!'},
 'locals2': {'locals1': {'var': 'var!'}, 'var': 'var!'},
 'var': 'var!'}
局部变量_1将包含var; 局部变量_2将包含var和局部变量_1;和 局部变量_3将包含var、局部变量_1和局部变量_2

# A function calls locals() several times, and returns them ...
def func():
  var = 'var!'
  locals_1 = locals()
  locals_2 = locals()
  locals_3 = locals()
  return locals_1, locals_2, locals_3

# func is called ...
locals_1, locals_2, locals_3 = func()

# display results ...
print 'locals_1:', locals_1
print 'locals_2:', locals_2
print 'locals_3:', locals_3
结果如下:

locals_1: {'var': 'var!', 'locals_1': {...}, 'locals_2': {...}}
locals_2: {'var': 'var!', 'locals_1': {...}, 'locals_2': {...}}
locals_3: {'var': 'var!', 'locals_1': {...}, 'locals_2': {...}}
这种模式似乎是,(n)次呼叫本地人,所有
返回的本地人口述是相同的,它们都包括 第一(n-1)个本地人听写

有人能解释一下吗

更具体地说:

为什么本地人包括自己

为什么本地人1包括本地人2?当 是否创建或执行func

为什么本地人3不包括在任何地方

“{…}”是否表示“无限递归”?有点像 那些镜子面对面的照片?

让我们运行以下代码:

def func():
  var = 'var!'
  locals_1 = locals()
  print(id(locals_1), id(locals()), locals())
  locals_2 = locals()
  print(id(locals_2), id(locals()), locals())
  locals_3 = locals()
  print(id(locals_3), id(locals()), locals())
  return locals_1, locals_2, locals_3


func()
这将出现在输出中:

44860744 44860744 {'locals_1': {...}, 'var': 'var!'}
44860744 44860744 {'locals_2': {...}, 'locals_1': {...}, 'var': 'var!'}
44860744 44860744 {'locals_2': {...}, 'locals_3': {...}, 'locals_1': {...}, 'var': 'var!'}
locals()
此处按预期增长,但是您将引用分配给
locals()
,而不是将
locals()
的值分配给每个变量

每次赋值后,
locals()
都会发生变化,但引用不发生变化,因此每个变量都指向同一个对象。在我的输出中,所有对象
id
s都相等,这就是证明

更详细的解释

这些变量与该对象具有相同的链接(引用)。基本上,Python中的所有变量都是引用(类似于指针的概念)

他们完全不知道
locals()
有什么值,他们只知道在需要时(当变量在某个地方使用时)从哪里获得它。对
locals()
的更改不会影响这些变量

在函数的末尾,您将返回三个变量,这是您在打印它们时发生的情况:

print(locals_N) -> 1. Get object referenced in locals_N
                   2. Return the value of that object
看到了吗?因此,这就是为什么它们具有完全相同的值,
locals()


如果再次(以某种方式)更改
locals()
,然后运行print语句,会打印3次什么?是的,
locals()的新值
我喜欢你的问题,真的很好

是的,
locals()
有点神奇,但是通过你的方法,你很快就会得到它,并且会喜欢它

关键概念 字典是按引用而不是按值分配的 如您所见,
a
b
被修改的那一刻被间接更改,因为
a
b
都指向内存中相同的数据结构

locals()
正在返回包含所有局部变量的字典 编辑:澄清此dict何时更新

因此,在调用
locals()
时存在的所有局部变量都存在于这里。如果您随后调用
locals()
,则此词典将在调用时更新

回答你的问题 为什么本地人包括自己? 因为
locals\u 1
是对所有本地定义变量的字典的引用。只要
locals\u 1
成为本地名称空间的一部分,它就会返回字典
locals()
的一部分

为什么本地人1包括本地人2?创建或执行func时是否分配了局部变量_1? 与前一个答案相同的答案适用

为什么本地人3不包括在任何地方? 这是你问题中最难的部分。经过一些研究,我发现了关于这个主题的优秀文章:

事实是,
locals()
返回一个字典,其中包含对所有局部变量的引用。但棘手的部分是,它不是直接的结构,它是一个字典,目前只更新,
locals()
被调用

这解释了您的结果中缺少局部变量3的原因。所有结果都指向同一个字典,但在引入
locals\u 3
变量后,它不会得到更新

当我在返回之前添加另一个print
locals()
时,我在那里找到了它,但没有

不明飞行物

“{…}”是否表示“无限递归”?有点像那些镜子面对面的照片? 我会把它读作“还有更多的东西”。但我认为,您是对的,这是一个用于打印递归数据结构的解决方案。如果没有这样的解决方案,词典就无法在有限的时间内真正印刷出来

奖金-在string.format()中使用**locals() 有一种习惯用法,其中locals()大大缩短了您的代码,格式为string.format()


frostnational和扬·弗尔辛斯基已经对幕后发生的事情给出了很好的解释。下面是一个关于实现您最初期望的行为的小补充。您可以使用
copy
方法创建
locals()
dict的副本。更新
locals()
时,该副本不会更新,因此它包含您期望的“快照”:

In [1]: def func():
   ...:     var = 'var!'
   ...:     locals1 = locals().copy()
   ...:     locals2 = locals().copy()
   ...:     locals3 = locals().copy()
   ...:     return locals1, locals2, locals3
   ...:

In [2]: locals1, locals2, locals3 = func()

In [3]: locals1
Out[3]: {'var': 'var!'}

In [4]: locals2
Out[4]: {'locals1': {'var': 'var!'}, 'var': 'var!'}

In [5]: locals3
Out[5]:
{'locals1': {'var': 'var!'},
 'locals2': {'locals1': {'var': 'var!'}, 'var': 'var!'},
 'var': 'var!'}

正如所料,每个副本只包含在调用
locals()
之前定义的变量。

我最初的问题是,“到底什么是
locals()
?” 以下是我目前(推测性)的理解,用Python写的:

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Python的locals()的性质是什么? 每个本地名称空间都有自己的名称空间表,可以 使用
局部变量
内置函数查看总数。 (事实上,名称空间表类似于保存“标识符”:对象项的dict;对于每个项,键是分配(或“绑定”)给对象的名称(以字符串形式)

在非全局级别调用时,
loca
name = "frost"
surname = "national"
print "The guy named {name} {surname} got great question.".format(**locals())
In [1]: def func():
   ...:     var = 'var!'
   ...:     locals1 = locals().copy()
   ...:     locals2 = locals().copy()
   ...:     locals3 = locals().copy()
   ...:     return locals1, locals2, locals3
   ...:

In [2]: locals1, locals2, locals3 = func()

In [3]: locals1
Out[3]: {'var': 'var!'}

In [4]: locals2
Out[4]: {'locals1': {'var': 'var!'}, 'var': 'var!'}

In [5]: locals3
Out[5]:
{'locals1': {'var': 'var!'},
 'locals2': {'locals1': {'var': 'var!'}, 'var': 'var!'},
 'var': 'var!'}
# A function copies locals() several times, and returns each result ...
def func():
    var = 'var!'
    locals_1 = locals().copy()
    locals_2 = locals().copy()
    locals_3 = locals().copy()
    return locals_1, locals_2, locals_3
locals_1: {'var': 'var!'}
locals_2: {'var': 'var!', 'locals_1': {'var': 'var!'}}
locals_3: {'var': 'var!', 'locals_1': {'var': 'var!'}, 'locals_2':{'var':'var!','locals_1': {'var': 'var!'}}}