为什么我对存在于局部作用域中的变量的调用在Python中不起作用?

为什么我对存在于局部作用域中的变量的调用在Python中不起作用?,python,Python,此代码是函数的一部分。当我使用正确的参数逐行运行函数时,它运行良好,但当我调用函数时,它似乎不起作用。以下三行代码及其输出来自函数调用: print(locals().keys()) dict_keys(['allpost', 'allpre', 'pre', 'post']) parentinfantstats=delete.bystats(mod='parentinfant',assessment=".*pii[1-3]plus",dta=sortFiltbyMod.copy()) 您可

此代码是函数的一部分。当我使用正确的参数逐行运行函数时,它运行良好,但当我调用函数时,它似乎不起作用。以下三行代码及其输出来自函数调用:

print(locals().keys())
dict_keys(['allpost', 'allpre', 'pre', 'post'])
parentinfantstats=delete.bystats(mod='parentinfant',assessment=".*pii[1-3]plus",dta=sortFiltbyMod.copy())
您可以看到“allpre”存在于我的本地作用域中。这行代码也在函数中起作用:

print(locals()['allpre'])
[15.0, 12.0, 10.0, 6.0, 12.0, 8.0, 5.0, 3.0]
parentinfantstats=delete.bystats(mod='parentinfant',assessment=".*pii[1-3]plus",dta=sortFiltbyMod.copy())
但由于某些原因,此代码不起作用:

print([locals()[k] for k in ['allpre']])
Traceback (most recent call last):
File "prepost.py", line 85, in <module>      parentinfantstats=delete.bystats(mod='parentinfant',assessment=".*pii[1-3]plus",dta=sortFiltbyMod.copy())
File "/mnt/m/safecare/prepost/delete.py", line 37, in bystats
print([locals()[k] for k in ['allpre']])
File "/mnt/m/safecare/prepost/delete.py", line 37, in <listcomp>
print([locals()[k] for k in ['allpre']])
KeyError: 'allpre'
parentinfantstats=delete.bystats(mod='parentinfant',assessment=".*pii[1-3]plus",dta=sortFiltbyMod.copy())

请在打印中尝试whitout[]

parentinfantstats=delete.bystats(mod='parentinfant',assessment=".*pii[1-3]plus",dta=sortFiltbyMod.copy())
print(locals()[k] for k in ['allpre'])

在Python3上,列表理解有自己的作用域和自己的局部变量
allpre
不是理解的局部变量之一。

从列表理解中调用
locals
将无法按预期方式工作(在Python 3中)。这是因为列表理解的主体在它自己的本地名称空间中运行,就像它是一个返回列表的函数一样。您可以在回溯中看到这一点,其中
显示为堆栈级别之一

parentinfantstats=delete.bystats(mod='parentinfant',assessment=".*pii[1-3]plus",dta=sortFiltbyMod.copy())

在Python2中,列表理解并没有做到这一点(但生成器表达式做到了)。他们旧行为的一个副作用是迭代变量(例如,
k
)将“泄漏”到周围的名称空间中,这通常是非常意外的。列表理解在类的顶层运行时也会中断,因为之前定义的类变量无法被理解函数访问(因为类没有作用域)。

自Python 3.0以来,列表理解有其局部作用域。这是为了防止

parentinfantstats=delete.bystats(mod='parentinfant',assessment=".*pii[1-3]plus",dta=sortFiltbyMod.copy())

parentinfantstats=delete.bystats(mod='parentinfant',assessment=".*pii[1-3]plus",dta=sortFiltbyMod.copy())
[…]注意列表理解有不同的语义:它们更接近list()构造函数中生成器表达式的语法糖,尤其是循环控制变量不再泄漏到周围的范围中

parentinfantstats=delete.bystats(mod='parentinfant',assessment=".*pii[1-3]plus",dta=sortFiltbyMod.copy())

发布函数。我找不到任何问题。它应该会起作用。它对我有用。在运行最终打印之前再次检查locals()。它仍然存在。这三条打印语句是一行。刚刚发布了整个功能。您确定上面两条打印语句打印的是您提到的同一条消息吗?使用
print(['allpre']]中的[locals()[k]表示k)
表示第三条语句。如果仍然不起作用,请尝试删除第二条打印语句。这将创建生成器对象。我将这些打印语句放入以进行故障排除。函数的最后一行是
返回{k:[op(eval(k)),用于[mean,median,min,max,len,stdev]]中的op,用于['allpre','allpost','allch','allpctch']}中的k。有没有一种方法可以理解访问函数的名称空间?一般来说,不需要到处传递变量名。但是,由于需要将名称作为输出字典的键,因此不能完全跳过它们。也许您可以直接将值与其名称一起传递,而不需要
eval
?未测试:
返回{k:op(v)for op in[[mean,median,min,max,len,stdev]]for k,v in[('allpre',allpre),('allpost',allpost),('allch',allch),('allpctch',allpctch)]
最好只返回一个值序列,其中顺序意味着哪个值是哪个值。