命名空间字典混淆



我正试图理解为什么其中一个失败而另一个成功。

my_prd = { 'server': 'prd.my.company.com' }
my_lab = { 'server': 'prd.my.company.com' }
my_srv = {}
def test_fails(which):
if which == 'prd':
my_srv = my_prd
else:
my_srv = my_lab

def test_works(which):
if which == 'prd':
my_srv['server'] = my_prd['server']
else:
my_srv['server'] = my_lab['server']

输出:

fails: my_srv={}
works: my_srv={'server': 'prd.my.company.com'}

我要把我的引用逻辑移到我的函数之外来处理这个问题,但我想了解为什么my_srv在足够的范围内,我可以给它赋值,但在范围内不足以被引用或copy()?

test_fails()中,您分配my_srv = my_prd(或my_srv = my_lab)。这意味着my_srv是一个指向my_prd的变量,就像我们所说的"指针"一样。在其他语言中(在Python中,"一切都是指针")。您可以将my_srv用于test_fails()的其余部分,但是一旦离开该函数,该局部变量将被遗忘,并且my_srv将再次引用空字典。

也许这将有助于你所希望做的:

>>> my_prd = { 'server': 'prd.my.company.com' }
>>> my_lab = { 'server': 'prd.my.company.com' }
>>> my_srv = {}
>>> def test_fails(which):
...     if which == 'prd':
...         my_srv = my_prd
...     else:
...         my_srv = my_lab
...     my_srv["key"] = "item"
...
>>> print(my_prd)
{'server': 'prd.my.company.com'}
>>> test_fails("prd")
>>> print(my_prd)
{'server': 'prd.my.company.com', 'key': 'item'}

当您在函数中创建变量时,该变量默认为本地变量,这意味着一旦您退出该函数,该变量将不复存在(并且不会与全局变量存储在同一位置,因此具有相同名称的全局变量和局部变量不是问题),这就是您通过编写

所做的
my_srv = my_prd

当你退出test_fails()并访问my_srv时,python会在全局变量中查找my_srv,它发现my_srv未被修改并且等于{},全局my_srv和本地my_srv从来没有关联,它们只是碰巧有相同的名称,但总是驻留在两个不同的环境中。

然而,在test_works()中,您不创建任何变量,您告诉python在已经存在的字典中创建一个额外的键/值对,my_srv全局变量,因此当您退出test_works()时,您的工作仍然存在。

正如其他人提到的,Python默认创建局部变量。有一些关键字,如global和nonlocal (Python 3.x)可以改变名称空间的处理方式。编辑:

在我的例子中,这行得通:

def test_fails(which):
global my_srv  #<<< Add this and it will work
if which == 'prd':
my_srv = my_prd
else:
my_srv = my_lab

我找到的一个很好的参考是:全局变量与局部变量和命名空间

最新更新