【问题标题】:Why does flake8 say "undefined name" for something I defined in an `as` block?为什么 flake8 对我在“as”块中定义的东西说“未定义的名称”?
【发布时间】:2020-06-24 09:08:03
【问题描述】:

考虑这个例子:

def f(*args, **kwargs):
    print(*args, **kwargs)


def do_something(f):
    f()


try:
    1/0
except Exception as e:
    print('Caught')
    do_something(lambda: f(e))

还有 flake8 输出:

a.py:11:1: F841 local variable 'e' is assigned to but never used
a.py:13:28: F821 undefined name 'e'

为什么 flake8 会抱怨?代码似乎运行正常。

【问题讨论】:

    标签: python flake8


    【解决方案1】:

    从 python 3 开始,except: 块仅在块本身期间定义名称

    你可以想到

    try:
       ...  # 1
    except Exception as e:
       ...  # 2
    

    如下:

    try:
        ...  # 1
    except Exception as e:
        try:
            ...  # 2
        finally:
            del e
    

    对于 pyflakes(产生 F 错误代码的工具)中的内部函数(包括您的示例中的 lambdas),名称的评估被推迟到函数结束。这是为了处理这样的情况:

    def f():
        def g():
            print(x)  # it looks like `x` doesn't exist yet from a syntax perspective
    
       x = 1
       g()
    

    第三,pyflakes 不会对语句进行任何分支或上下文分析,你可以认为它们都被压扁到左边,没有分支或块

    所以在你的例子中,pyflakes 大致看到:

    1/0
    e = ...  # sys.exc_info()[1]
    print('Caught')
    do_something(lambda: f(e))
    del e
    

    并且由于函数 e 的末尾是 deld,pyflakes 将其视为〜可能未定义。虽然对人类来说很明显它是在定义它的地方调用的,但您需要在实践中解决停止问题才能知道它是否未定义(您基本上需要运行代码分析每个可能的分支)

    对于“问题”(尽管我认为它无法解决),跟踪器中有这个:https://github.com/PyCQA/pyflakes/issues/265


    免责声明:我是flake8的当前维护者,也是pyflakes的维护者之一

    【讨论】:

      猜你喜欢
      • 2019-11-27
      • 2019-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-24
      • 2021-12-12
      • 2023-03-16
      相关资源
      最近更新 更多