Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用上下文管理器似乎改变了对变量的访问_Python_Scoping_Contextmanager - Fatal编程技术网

Python 使用上下文管理器似乎改变了对变量的访问

Python 使用上下文管理器似乎改变了对变量的访问,python,scoping,contextmanager,Python,Scoping,Contextmanager,我有一个工作程序,它为列表的每一项(比如一本书)调用一个API,以获取关于这本书的元数据。它将书:元数据存储在dict中以供使用。这会导致用户在元数据收集过程中等待,因此避免过度调用我将dict持久化到CSV,并在进行上述API调用之前加载它,以确保仅在必要时获得响应 但是,当我引入上下文管理器来读取持久化dict,然后在函数(“gatherfiles()”)中调用if note there逻辑时,第三个函数将无法再访问它 当我在主函数中调用时,我可以看到gatherfiles()返回dict,

我有一个工作程序,它为列表的每一项(比如一本书)调用一个API,以获取关于这本书的元数据。它将书:元数据存储在dict中以供使用。这会导致用户在元数据收集过程中等待,因此避免过度调用我将dict持久化到CSV,并在进行上述API调用之前加载它,以确保仅在必要时获得响应

但是,当我引入上下文管理器来读取持久化dict,然后在函数(“gatherfiles()”)中调用if note there逻辑时,第三个函数将无法再访问它

当我在主函数中调用时,我可以看到gatherfiles()返回dict,但当我进行第三次函数调用(调用“pickabook()”)时,我得到一个keyrerror,并看到一个空字典

我在下面列出了代码的修订版本。我的猜测是,不知何故,上下文管理器改变了范围(因此它将一个shimdict视为全局,另一个视为本地),但考虑到我可以在线阅读的内容,这似乎并不正确。这里有没有不难看的想法



所以我完全理解我可以使用全局或将本地dict传递给函数来解决这个问题,但我想知道为什么添加上下文管理器会改变行为。

正如Waleed Khan所评论的,问题在于
main
gatherfiles
函数中的
shimdict
变量与
shimdict
全局变量不同。后者在模块顶部初始化为en empty dictionary,并保持为空。这是
pickabook
试图从中弹出的内容。其他变量是其函数中的局部变量(在本例中,它们恰好引用相同的对象,但对于其他函数中具有相同名称的局部变量,情况并非如此)。默认情况下,Python在指定新名称时始终使用局部变量,除非使用
global
nonlocal
语句来指示Python使用其他方法

在这种特定情况下,可以通过以下两种方式之一使函数正常工作。您可以将
global shimdict
放在
main
gatherfiles
的顶部(如果是后者,您可以跳过
return
ing字典,因为以后仍将通过其全局名称访问它)

然而,更好的解决方案可能是完全去掉全局变量,并让
main
将其局部
shimdict
传递给
pickabook
。只需将
pickabook
函数声明更改为:

def pickabook(shimdict, book=None):
以及从
main
到以下位置的调用:

current = pickabook(shmdict, bookname)
编辑以回答问题编辑:

上下文管理器仍然无关紧要。您在编辑中显示的工作代码与问题原始部分中显示的非工作代码之间的真正区别在于,在后一部分中,您正在为名称
shimdict
赋值:

shimdict = dict((rows[0],rows[1]) for rows in reader)
在前者中,您仅为字典的各个项目分配:

shimdict[filename] = (returnedvalue)
前者在函数内部创建新的本地字典(除非使用
global
语句)。后者从不这样做,它总是访问全局版本的
shimdict

因此,我认为另一种解决方案是重写上下文管理器,使用代码将每个项单独分配到字典中,而不是使用生成器表达式创建整个内容:

with open('test.csv', 'rb') as f:
    reader = csv.reader(f,)
    for row in reader:
        shimdict[row[0]] = row[1]

我仍然建议避免使用全局变量,因为这通常会导致复杂的代码,其中包含难以修复的bug。

区别在于您将其放入函数中,而不是使用上下文管理器。在函数中,使用
global shimdict
获得对
shimdict
的写入权限。您好-谢谢您的回答。我的问题问得不够明确-你能对编辑发表评论吗?
shimdict[filename] = (returnedvalue)
with open('test.csv', 'rb') as f:
    reader = csv.reader(f,)
    for row in reader:
        shimdict[row[0]] = row[1]