Python 作用域、函数、块和非本地

问题描述

我对范围感到困惑。 如果有的话,在“函数内”分配变量和在“函数内”分配变量之间的区别是什么? 缩进块?我读过很多地方,if 和 try 块没有创建或拥有自己的范围,但我也有 读到变量的范围是定义它的最里面的块。 我用谷歌搜索但无法在 if 或 try 块中找到非本地示例。

def sixdig2iso(pathfrom):
    os.chdir(pathfrom)
    filelist = os.listdir()
    nonlocal xfrs
    xfrs = 0

PyCharm 说非局部变量“xfrs”必须绑定在外部函数范围内 这不是这个函数的最外层吗?那么有什么问题呢? 这个函数的最外层是 != 一个外部函数吗?即使每个的作用域与那些相同函数的内部部分不同?!

if xfrs == 0:
    restofit = frs[1:]
    try:
        convert = datetime.strptime(mm,'%m%d%y')
    except ValueError as e:
        logger.info(f"For {filename},mm is: {mm} - and the error is: {e}")
        count_err += 1
    ender = ' '.join(restofit)
    fronter = str(convert.date())

PyCharm 表示在赋值之前“可能”使用第二个转换

我尝试创建一个内部函数

def sixdig2iso(pathfrom):
    """Converts six digit dates into proper datetime format in place."""
    os.chdir(pathfrom)
    filelist = os.listdir()
    nonlocal xfrs
    xfrs = 0
    def blockscope():

但 PyCharm 给了我同样的“非局部变量 'xfrs' 必须绑定在外部函数范围内”警告。

更新 我的回复太长,无法发表评论

  1. “我们不得不猜测,因为你没有提供一个完整的例子” 对于这些问题,我似乎永远无法在“不够”和“太多”信息之间取得平衡。我可能不认为你说的缺失的部分是相关的,这首先影响了我对问题的理解。

  2. “不管你在这函数内创建了多少个函数嵌套,nonlocal 只会向外看。” 看,我不知道。然后我推断,它也只是看起来“向上”,对吗?

  3. “由于 .strptime() 可能会因异常而失败,convert 可能最终没有被赋值,因为您没有在 try 块之外初始化 convert。 “ 好的,很好,很有帮助。我没有意识到(而且 PyCharm 没有像你刚才那样解释)这就是 PyCharm 所说的。但这也是我对 try 块的“范围”感到困惑的原因。

解决方法

在您提供的第一个示例中,xfrs 仅在您作为示例提供的函数中定义。我们不得不猜测,因为你没有提供一个完整的例子,但是来自 PyCharm 的消息表明你没有在另一个已经定义了这样一个标识符的函数中定义这个函数,并且全局中没有 xfrs范围。

在第二个示例中,您将 convert 分配给 try 块的 try .. except 部分中的 .strptime()。由于 convert 可能会因异常而失败,因此 convert 可能最终没有被赋值,因为您没有在 try 块之外初始化 nonlocal。所以,PyCharm 是正确的(同样,我们必须假设您没有提供完整的示例。

最后,在第三个示例中,您开始在函数内部定义一个函数,但仍然将 sixdig2iso() 应用于 nonlocal 范围内的变量 - 无论您有多少函数嵌套在这个函数内部创建,nonlocal 只向外看。

x = 0 def outer(): x = 1 def inner(): nonlocal x x += 1 return x return x,inner v,f = outer() print(x,v,f()) 的典型用法是@Carcigenicate 在其链接中提供的(此处进行了一些修改):

outer()

2 返回的函数在调用时会产生 x,因为它的非局部变量 inner()x 与局部变量 outer() 相同1,从 1 开始,并在调用函数时添加 outer()

你可以看出这是怎么回事,因为 1 返回的值是 f(),但是调用返回的函数 2 会返回 x。始终保持全局 nonlocal 不变。

尝试将 global 更改为 0 1 2 ,您会发现结果更改为:

0 1 1

致:

nonlocal

我希望这有助于解释 <Formik initialValues={{ name: "",}} onSubmit={(values: any) => console.log(values)} > {({ handleSubmit,setFieldValue }) => ( <Form noValidate autoComplete="off" onSubmit={handleSubmit}> <TextField onChange={(event) => setFieldValue("name",event.target.value)} type="text" label="Name" /> </Form> )} </Formik> 的情况。