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

2024-10-02 22:36:27 发布

您现在位置:Python中文网/ 问答频道 /正文

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

print(locals().keys())
dict_keys(['allpost', 'allpre', 'pre', 'post'])

您可以看到“allpre”存在于我的本地作用域中。这一行代码也在函数中起作用:

print(locals()['allpre'])
[15.0, 12.0, 10.0, 6.0, 12.0, 8.0, 5.0, 3.0]

但由于某些原因,此代码不起作用:

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'

有人对可能出现的问题有什么建议吗?我会举一个例子,但似乎不能重复这个问题。你知道吗

这就是整个功能:

import re
from statistics import mean,median,stdev

def bystats(*,mod,assessment,dta):
    varz=dta[mod]               
    alab=[i for i in varz if re.match(assessment.lower(),i.lower())]
    alab.insert(0,'prepost')
    alab.insert(0,'cact_familycodenormalized')
    alst=[varz[i] for i in alab] # [ID,prepost,assessment]
    bymodprepost=[list(row) for row in zip(*alst) if row[1] in [1,2]] # [ID,prepost,assessment] if prepost 1 or 2
    bymodpost=[i for i in bymodprepost if i[1]==2] # [ID,prepost,assessment] if prepost was 2 (post)
    bymodpre=[i for i in bymodprepost if i[0] in [ids[0] for ids in bymodpost] and i[1]==1] # [ID,prepost,assessment] if ID had a post test

    allpre,allpost,allch,allpctch=[],[],[],[]
    for pre in bymodpre:
        post=[i for i in bymodpost if i[0].upper().strip()==pre[0].upper().strip()][0] # find matching post test
        if any([True for i in pre[2:]+post[2:] if float(i)<0]): continue # cannot have negative number
        sumpre=sum([float(i) for i in pre[2:]]) # sum of pre test assessments
        allpre.append(sumpre)
        sumpost=sum([float(i) for i in post[2:]]) # sum post test assessments
        allpost.append(sumpost)
        ch=sumpost-sumpre       # change from pre to post
        allch.append(ch)
        pctch=round(ch/sumpre*100,1) # percent change from pre to post
        allpctch.append(pctch)
    print(locals().keys())
    print(locals()['allpre'])
    print(locals()[k] for k in ['allpre'])

这是函数调用:

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

Tags: 代码inidmodforifdeletepost
3条回答

自python3.0以来,列表理解有其局部范围。这是为了防止scope leak。你知道吗

https://docs.python.org/3.0/whatsnew/3.0.html

[...] note that list comprehensions have different semantics: they are closer to syntactic sugar for a generator expression inside a list() constructor, and in particular the loop control variables are no longer leaked into the surrounding scope.

在你的印刷品中试用whiteout[]

print(locals()[k] for k in ['allpre'])

从列表理解中调用locals不会按您期望的方式工作(在python3中)。这是因为列表理解的主体在它自己的本地名称空间中运行,就像它是一个返回列表的函数一样。您可以在回溯中看到这一点,其中<listcomp>显示为堆栈级别之一。你知道吗

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

相关问题 更多 >