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
变量后,它不会得到更新
当我在返回之前添加另一个printlocals()
时,我在那里找到了它,但没有
不明飞行物
“{…}”是否表示“无限递归”?有点像那些镜子面对面的照片?
我会把它读作“还有更多的东西”。但我认为,您是对的,这是一个用于打印递归数据结构的解决方案。如果没有这样的解决方案,词典就无法在有限的时间内真正印刷出来
奖金-在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!'}}}