【问题标题】:"Using variable X before assignment" error pops up for no obvious reason无明显原因弹出“在赋值前使用变量 X”错误
【发布时间】:2018-10-18 17:24:03
【问题描述】:

我已阅读过有关此错误的信息,但问题是我认为我不应该在这里收到此错误,而且我从未见过有人遇到此问题。这是我的代码:

def substituie(caractere):
    lista_optiuni = genereaza_lista_substitutii(caractere)

    global sir
    sir = sterge_lambda(sir)
    while lista_optiuni != []:
        index = randrange(0,len(lista_optiuni))
        if len(sir) + len(lista_optiuni[index])-1 > 60:
             lista_optiuni.remove(lista_optiuni[index])
        else: 
             sir = sir.replace(caractere,lista_optiuni[index],1)
             sir = sterge_lambda(sir)
             return True
    return False

问题在于我的变量“Sir”。我有一个名为“Sir”的外部变量,我希望我的函数在不将其作为参数传递的情况下更改它的某些方面。所以我在函数内将它声明为全局,但我仍然得到一个错误,好像我的函数不知道这个变量是谁。此外,代码工作正常,完全符合我的要求,但它下面的红线和“源代码管理”选项卡中的“1 个问题”警告真的让我很困扰。这发生在我的代码中的更多地方,例如:

global sir
sir = sir.replace(caractere,lista_optiuni[index],1)

这行代码在同一个函数中也出现了同样的错误,但由于某种原因它不再出现,而是专注于我函数的第 3 行代码。此外,sterge_lambda(sir) 只是将某个字符替换为 '',不确定单行函数是否值得制作,但无论如何。

P.S.:代码是在 VSCode 中用 Python 3.7 编写的。

【问题讨论】:

  • 鉴于 Python 中 scope 的规则,通过在函数外部(或“上方”)初始化 sir,它应该已经在范围内,即使没有global 声明。
  • 我读了一些关于范围规则以及如何使用全局变量的信息,我很确定我做对了,所以我可以看到 2 种不同的可能性:1)我错了 2 ) IntelliSense、Python Linter、Interpreter 或任何负责指出这些“问题”的东西,都将其标记为误报。
  • 尝试删除global 声明,看看问题是否消失
  • @DanielR.Livingston:不,没有global,分配将使其成为本地。这只是一个 pylint 误报。

标签: python python-3.x visual-studio-code


【解决方案1】:

Visual Studio 使用的默认 linter pylint 正在抱怨,因为在调用 substituie() 和语句 @987654325 中的表达式 sterge_lambda(sir) 之前,它没有找到任何可以为 sir 赋值的代码@ 正在运行。

这可能表明您的代码有问题,因为在真正执行 subtituie() 时,任何地方都没有设置全局名称 sir,然后您会得到 NameError: name 'sir' is not defined 异常。

如果您确定这在您的项目中永远不会发生,您可以通过在同一行添加 # pylint: disable=... 条目来告诉 pylint 忽略此特定问题,其中 ... 被替换为错误代码当您将鼠标悬停在红线上时,在对话框中可见:

sir = sterge_lambda(sir)  # pylint: disable=E0601

或者您可以使用符号名称,对于 E0601,used-before-assignment

sir = sterge_lambda(sir)  # pylint: disable=used-before-assignment

您可以通过在命令行上运行 pylint --list-msgs 来查看消息名称及其错误代码的完整列表,或者您可以使用 pylint --help-msg=<code-or-name> 访问有关单个消息的信息。

【讨论】:

  • 我已经测试了很多次代码,它从来没有因为在调用之前没有被赋值而失败。我什至调试并逐步运行它至少 10 次(出于其他原因),并且字符串总是按时初始化。在声明和初始化内部使用的全局变量之前定义函数会导致这样的问题吗?
  • @AdrianBunea:这只是误报。 pylint 并不完美,它不会运行代码,也无法解决所有可能的情况。它可能是错误的,如果您知道它是错误的,只需禁用该行的消息即可。
  • @AdrianBunea:另外,linter 只是一种工具,可以帮助您编写更好的代码并在错误发生之前检测到错误。在这里给你一条消息的 linter 并不意味着你的代码真的被破坏了,而且 linter 并不能捕捉到所有的 bug。
【解决方案2】:

似乎我定义函数和声明在所述函数中使用的全局变量的顺序很重要。而:

def substituie(caractere):
    lista_optiuni = genereaza_lista_substitutii(caractere)

    global sir
    sir = sterge_lambda(sir)
    while lista_optiuni != []:
       index = randrange(0,len(lista_optiuni))
       if len(sir) + len(lista_optiuni[index])-1 > 60:
           lista_optiuni.remove(lista_optiuni[index])
       else: 
           sir = sir.replace(caractere,lista_optiuni[index],1)
           sir = sterge_lambda(sir)
           return True
    return False

sir = start

会导致弹出错误信息,虽然执行还是正常进行,这段代码:

sir = start

def substituie(caractere):
    lista_optiuni = genereaza_lista_substitutii(caractere)

    global sir
    sir = sterge_lambda(sir)
    while lista_optiuni != []:
       index = randrange(0,len(lista_optiuni))
       if len(sir) + len(lista_optiuni[index])-1 > 60:
           lista_optiuni.remove(lista_optiuni[index])
       else: 
           sir = sir.replace(caractere,lista_optiuni[index],1)
           sir = sterge_lambda(sir)
           return True
    return False

不抱怨任何问题。唯一的区别是在第一个版本中,函数中使用的变量是在函数定义之后声明的。这不是执行问题,只是解释的方式。

【讨论】:

  • either 代码没有问题,只要sir = start 在第一次调用substituie 之前。
  • 没错,没问题,完美执行。但是 pylint 认为它不喜欢第一个版本并给了我一个误报。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多