【问题标题】:Python scope, functions, blocks and non-localPython 范围、函数、块和非本地
【发布时间】:2021-05-30 12:31:59
【问题描述】:

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

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 块的“范围”感到困惑的原因。

【问题讨论】:

  • Python 没有块作用域,所以我不确定“变量的作用域是定义它的最里面的块”的上下文是什么。我通常在this 这样的情况下使用nonlocal。返回后形成闭包来引用变量是很好的。

标签: python scope python-nonlocal


【解决方案1】:

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

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

最后,在第三个示例中,您开始在函数内部定义一个函数,但仍将 nonlocal 应用于 sixdig2iso() 范围内的变量 - 在此函数中创建多少个函数嵌套并不重要, nonlocal 只看外面。

nonlocal 的典型用法是 @Carcigenicate 在其链接中提供的(此处进行了一些修改):

x = 0


def outer():
    x = 1

    def inner():
        nonlocal x
        x += 1
        return x

    return x, inner


v, f = outer()
print(x, v, f())

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

你可以知道会发生什么,因为outer() 返回的值是1,但调用返回的函数f() 会返回2。一直以来,全球x 都没有受到影响。

尝试将nonlocal 更改为global,您会发现结果更改为:

0 1 2

收件人:

0 1 1

我希望这有助于解释 nonlocal 的情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-29
    • 1970-01-01
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多