【问题标题】:Returning Variables in Functions Python Not Working Right在 Python 函数中返回变量不能正常工作
【发布时间】:2013-08-04 03:43:31
【问题描述】:

我一直试图在一个变量中的函数中返回一个变量并在它之外使用它:

test = 0

def testing():
    test = 1
    return test

testing()
print(test)

但是当我运行它时,结果是 0。我该如何解决这个问题?

【问题讨论】:

  • 把全局变量test改成g_test就明白了。它们是两个完全不同的变量,使用相同的名称只会让您自己感到困惑。
  • 在撰写本文时,有 7 票赞成看起来正确的答案。但我认为没有人真正解释过这一点。您的代码中真正的故障(它不起作用的唯一原因)是,当您执行函数调用时,您没有捕获返回值。然后打印一个原始未更改的全局变量。关于范围的评论是正确的。函数内部的“test”是局部作用域,是一个不会更改函数外部的全局“test”变量的副本。
  • 如果您是 Python 新手,您应该在 Google 上搜索“mutating vs nonmutating”并阅读 Stack Overflow 上的帖子,以便您使用列表并从看似相似的代码中获得不同的行为。如果您将“test”作为参数传递,您仍然必须返回并捕获它以使其工作。但是对于像列表这样的变异变量,这种行为是不同的。除了其他人已经为您的问题提供的代码修复之外,希望您发现这对您有所帮助。
  • 哎呀 - 这是一个 3 岁的帖子。我想我只是为了完整性而写的,以便在寻求解决问题时偶然发现此线程的任何人。

标签: python variables return-value


【解决方案1】:

您有点搞砸了范围和/或分配。试试这个:

def testing():
    test = 1
    return test

test = testing()
print(test)

解释:testing 内部的test 与模块内部的test 不同。您必须在模块级别分配它才能获得预期的结果。

【讨论】:

  • 谢谢你。我有一段更复杂的代码,其中包含递归,显然出于同样的原因失败了。在所有代码中都很难看到。我认为这个简单的问题和答案可能让我找到了解决方案。 :-)
【解决方案2】:

因为你在函数中声明了test,它不是一个全局变量,因此你不能访问你在函数之外创建的变量test,因为它们是不同的作用域

如果你想return test到一个变量,你必须这样做

result = testing()
print(result)

或者,您也可以添加global 声明:

test = 0

def testing():
    global test
    test = 1
    return test

testing()
print(test)

顺便说一句,在做条件语句时,1==1 周围不需要括号:)。

【讨论】:

    【解决方案3】:

    在函数testing() 中,您正在创建一个新变量test不是指的是已经存在的变量。如果你想这样做,你应该在顶部使用global 语句,如下所示:

    def testing():
        global test
        ...etc...
    

    【讨论】:

    • 这也很有用,但另一个答案突出显示了代码中可能存在的错误(未捕获返回值),因此它作为解决方案具有更广泛的含义,并且更有可能帮助发布者找到发生了什么可能导致此示例的实际代码中的错误。作为 Python 的新手,我没有意识到你可以按照你的答案去做,这可能会帮助我处理其他用例,所以感谢发帖。
    【解决方案4】:

    函数内的test 变量没有全局范围。因此,如果您想将返回值存储在变量中并在之后输出,您可以执行以下操作:

    result = testing()
    print(result)
    

    【讨论】:

      【解决方案5】:

      TLDR:return 值必须分配到调用站点的某个东西。

      test = testing()
      

      Python 中的函数有自己的作用域。它在进入(调用)函数时创建,并在离开时销毁。在作用域内分配给 name 会使该名称成为该作用域的本地名称 - 导致它与作用域一起被销毁。

      # start outer scope
      test = 0  # create name outer:test
      
      def testing():
          # start inner scope
          test = 1  # create name outer.testing:test
          return test
          # end inner scope
          # destroy name outer.testing:test
      
      testing()  # new temporary inner scope outer.testing
      print(test)  # use name outer:test
      # end outer scope
      

      值得注意的是,内部范围内的名称可能来自外部范围的“shadow”名称。虽然名称test 存在于testing 和外部范围中,但它指的不是同一个东西。这有两个重要的含义:

      1. 分配给 inner test 不会影响 outer test
      2. testing 的末尾,内部 test 被销毁,只剩下外部 test

      这就是为什么调用testing() 没有达到预期效果的原因:它从不修改传递给print 的外部test


      The return statement defines the value returned by calling a function. 它确实返回名称,只返回指向的值。

      def testing():
          test = 1  # test refers to the value 1
          return test  # return test => value 1
      

      函数返回的值与任何其他值一样 - 无论是来自文字、查找还是其他。最重要的是,除非您将其分配给名称或直接使用,否则该值不会持久存在。

      testing()  # call test, discard its value
      test = testing()  # call test, store its value as `test`
      print(testing())  # call test, use its value in `print`
      

      因此,为了从函数中返回某些内容以供以后使用,您必须将结果存储到名称中。然后,您可以在以后的语句中使用该名称。您的案例的一个最小示例如下所示:

      # we already can define testing here
      # it is overwritten later on, then
      
      def testing():
          # all names we use inside of testing are gone at the end
          # if we just want a value, we can skip temporary names
          return 1
      
      # store the return value of testing() for later use
      test = testing()
      print(test)
      

      附录:函数可以修改其包含范围。但是,必须将名称显式声明为来自外部作用域。

      nonlocalglobal 关键字允许从外部范围修改名称。 nonlocal 是最接近匹配函数范围内的名称。 global 是模块范围内的名称,与中间的任何函数无关。

      test = 0
      
      def increment():
          global test  # declare test as belonging to a specific scope
          test += 1
          # no need to return something
          # we already modified the outer `test`
      
      print(test)  # 0
      increment()
      print(test)  # 1
      

      请注意,修改外部名称通常是反模式的标志,globals 比nonlocals 更是如此。除了小脚本之外,很难追踪访问和修改globals 的内容。通常,使用类或生成器来保存状态更合适。

      一个函数总是可以从它的包含范围读取名字,只要它从不写入相同的名字。这样的closures 非常容易创建,而且无需修改,更容易追踪。请注意,在函数中修改名称 anywhere 会使其成为本地名称,除非声明为 globalnonlocal

      test = 0
      
      def increment():
          global test
          test += 1
      
      def show_test():
          # we never modify `test`, so it is fetched from the outside
          print(test)
      
      def show_and_increment1():  # this function is broken!
          print(test)  # `test` is *not* the outer one, since we modify it in the function
          test += 1  # modifying `test` makes it local for the *entire* function
      
      def show_and_increment2():  # this function works!
          global test  # force `test` to be global
          print(test)
          test += 1
      
      show_test()  # 0
      increment()
      show_test()  # 1
      show_and_increment2()  # 1
      show_and_increment2()  # 2
      show_and_increment2()  # 3
      show_test()  # 4
      show_and_increment1()  # UnboundLocalError: local variable 'test' referenced before assignment
      

      【讨论】:

        猜你喜欢
        • 2014-01-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-06
        相关资源
        最近更新 更多