2

我对在 python 中使用 if setdefault() 的全局变量的行为有点困惑:

请找到有关如何使用 setdefault 引用/解决此问题的示例代码,有人可以帮我澄清这里发生了什么吗?

解析变量的主文件:

#main
from test import *

fill_func()

print my_list
print my_dict

为变量赋值的测试文件:

#test

my_list = []
my_dict = {}

def fill_func():
    my_list = [1,2,3]
    print my_list
    my_dict.setdefault(0,[]).append('zero')
    print my_dict

输出 :

[1, 2, 3]
{0: ['zero']}
[]
{0: ['zero']}

我无法理解为什么从 main.py 调用时 list(my_list) 变量显示为空,而 my_dict 显示数据正常?

任何帮助表示赞赏。蒂亚!

#

样本测试文件 2

#test

my_list = []
my_dict = {}

def fill_func():
    def fill_list():
        global my_list
        my_list = [1,2,3]
        print my_list
    my_dict.setdefault(0,[]).append('zero')
    print my_dict
    fill_list()

输出:

{0: ['zero']}
[1, 2, 3]
[]
{0: ['zero']}

有人可以对第二个测试文件有所了解吗,请耐心等待,尝试了解基础知识:)

蒂亚!

4

4 回答 4

2

my_list被定义为内部的局部变量fill_func;这是隐藏在全局范围中定义的另一个 my_list 。

因此,您的代码首先调用fill_func打印本地的my_list,然后是默认字典。然后它退出函数并打印外部范围my_list和字典(没有阴影)

于 2017-10-03T05:36:54.587 回答
1

您正在创建一个与全局变量同名的局部变量。只需global my_list在函数顶部添加即可。

于 2017-10-03T05:38:48.980 回答
1

这是因为,正如您正确指出的那样,它与范围有关。my_list并且my_dict是全局的test.py,必须使用global限定符访问。也就是说,您的代码应该是:

# Edited to address comments (see explanation below)
def fill_func():
    global my_list  # this is necessary since you're updating the values
    global my_dict
    my_list.extend([1,2,3])
    print my_list
    my_dict.setdefault(0,[]).append('zero')
    print my_dict

编辑:

要同时更新列表和字典,必须扩展列表并修改字典(如您所做的那样) - 即实际更改其值。使用赋值运算符为其赋值只会改变变量所指的内容,而不是值本身。这就是为什么它不会在本地函数范围之外更新。而且,这也是为什么当我们使用其他方法修改这些变量的内容时它会更新的原因。

问题是当解析函数体时,在正常赋值或扩充赋值中使用的所有变量都被视为局部变量,因此当函数被调用时,Python 不会在全局范围内查找这些变量,因此会引发错误。因此,您需要将这些变量指定为全局变量,以告诉 Python 在全局范围内查找它们。

另一种选择是使用 list.extend()

(从这里:https ://stackoverflow.com/a/23436510/866930 。对此有用的附加参考是:https ://stackoverflow.com/a/31437415/866930 )

只要您没有同名的局部变量,您始终可以访问全局变量。当您要更改变量名称所指的对象时,您只需要 global 语句。

与此版本比较:

def fill_func():
    global my_list
    global my_dict
    my_list = [1,2,3]
    print my_list  # prints `[1, 2, 3]` here and `[]` in main
    my_dict = {1: 'a', 2: 'b'}
    print my_dict  # prints `{1: 'a', 2: 'b'}` here, and `{}` in main

如果不使用global,Python 会认为该变量在定义它的代码元素的范围内是本地的,因此global告诉解释器在globals符号表中查找(这些内容可以通过 访问globals()

于 2017-10-03T05:41:20.070 回答
0

您需要在函数中声明要使用全局变量。

你可以这样做

def fill_func():
    global my_list
    global my_dict
    my_list = [1,2,3]
    print my_list
    my_dict.setdefault(0,[]).append('zero')
    print my_dict

请注意,通常最好只对全局变量使用大写字母以避免混淆

于 2017-10-03T05:38:39.327 回答