【问题标题】:Why am I getting a local variable referenced before assignment error? [duplicate]为什么我在赋值错误之前得到一个局部变量的引用? [复制]
【发布时间】:2016-10-05 17:23:05
【问题描述】:

答案应该是2,因为首先调用了main() 函数,然后调用了first() 函数,覆盖了在任何函数之外定义的全局变量num = 0,因此将其呈现为一个变量全球范围。但是我收到以下错误:

UnboundLocalError: local variable 'num' referenced before assignment  

为什么会出现这个错误?

def first():
    num = num + 1

def main():
    num = 1
    first()
    print(num)

num = 0

num_result = main()

print(num_result) 

【问题讨论】:

    标签: python


    【解决方案1】:

    firstnum 内部未知。使用参数和return 语句。

    def first(num):
        return num + 1
    
    def main():
        num = 1
        num = first(num)
        return num
    
    num = 0
    
    num_result = main()
    
    print(num_result)
    

    【讨论】:

    • 难道不应该知道吗?因为 num = 0 是在全局范围内定义的,为什么不在 first() 函数内部定义呢?
    • 否,num 未使用全局范围定义。请不要在每个答案下发表相同的评论。尝试理解 Python 中的作用域。
    • 函数外的 num 变量叫什么,如果不是全局变量,它是什么?
    • 但这并不意味着它可以用于函数内部的赋值。如果你想做num = ...,你必须在first里面声明global num。但是使用全局变量被认为是不好的风格。
    【解决方案2】:

    OP 写道(强调我的):

    答案应该是 2,因为首先调用 main() 函数,然后调用 first() 函数,覆盖全局变量

    它没有覆盖全局变量。除非您将变量明确指定为全局变量,否则如果函数中对变量进行了任何赋值,则假定它是局部变量。另请参阅python tutorial on defining functions 声明(强调我的):

    更准确地说,函数中的所有变量赋值都将值存储在局部符号表中;而变量引用首先在局部符号表中查找,然后在封闭函数的局部符号表中查找,然后在全局符号表中查找,最后在内置名称表中查找。因此,全局变量不能在函数内直接赋值(除非在全局语句中命名),尽管它们可以被引用。

    documentation of the global statement(如果有人使用 Python 3 正在查看此内容,请同时查看(与global 相比)非常有用的nonlocal statement 及其PEP 3104)。

    要“修复”您的代码:

    def first():
        global num
        num = num + 1
    
    def main():
        global num
        num = 1
        first()
        print(num)
    
    num = 0
    
    num_result = main()
    
    print(num_result) 
    

    请不要以这种方式使用全局变量。 @LutzHorn has shown in his answer how to do it right.

    避免使用全局变量的原因是它们的效果很难测试,而且一旦代码变得足够复杂,就很难推理。如果每个函数都修改全局变量而不是正确地获取参数和返回值,那么一旦距离代码超过一周左右,就很难理解代码的实际作用。

    【讨论】:

    • 如果您查看代码,num = 0 是在任何函数之外定义的。那么它不应该有一个全局范围吗?
    • @Dr.Doom2020 否。在哪个范围内查找变量完全取决于函数体。 “如有疑问”,局部变量优先,并且局部范围是您分配给的任何名称的默认值。请阅读并尝试理解我链接的教程部分。如果您还有其他问题,请回来。 :-)
    • 变量 num 是全局变量,这意味着它可以在脚本中的所有函数中访问和更改。所以 num 在 main() 和 first() 中改变了
    • 不,除非你在函数内部声明global,否则它不能被改变。
    • 在一个美好的宇宙中,是的,您的常识理解是它应该如何工作。 Imo 这个全局 bs 是 python 唯一的缺点,一个简单的无关紧要的脚本中的一个简单的小东西可以成为绝对的噩梦。
    【解决方案3】:

    这是一个范围错误。首先,在您尝试添加一个之前没有 num 。如果变量在这个 bloc 中、在上层 bloc 中或如果它被声明为全局变量,则可以在 bloc 中调用它。

    要传递变量,可以使用函数的参数:

    def first(num):
        return num + 1
    
    def main():
        shmilblik = first(1)
        print(shmilblik)
    

    【讨论】:

      【解决方案4】:

      “num”未在函数“first”中定义。它不是全局变量,它超出了“第一”的范围。要使其全局化,只需像这样编辑您的函数:

      def first():
          global num
          num = num + 1
      

      在我看来,使用全局变量是不好的做法。你可以通过使用参数和这样的返回来达到同样的效果:

      def first(num):
          return num + 1
      
      def main(num):
          num = 1
          num = first(num)
          print(num)
          return num
      
      num = 0
      
      num_result = main(num)
      
      print(num_result) 
      

      【讨论】:

      • num 是在任何函数之外定义的。因此它应该具有全局范围。
      【解决方案5】:

      变量 num 只是在 main 方法中初始化,你没有在 first() 方法中初始化它。所以你必须把它交给 first()-Method。

      def first(num):
          return num + 1
      
      def main():
          num = 1
          num = first(num)
          return num
      
      num = 0
      
      num_result = main()
      
      print(num_result)
      

      【讨论】:

      • 我已经在两个函数之外对其进行了初始化,所以它应该具有全局范围。
      猜你喜欢
      • 1970-01-01
      • 2021-02-18
      • 1970-01-01
      • 2022-09-28
      • 1970-01-01
      • 2020-05-28
      • 1970-01-01
      • 1970-01-01
      • 2015-02-08
      相关资源
      最近更新 更多