【问题标题】:UnboundLocalError in recursive call of nested function [duplicate]嵌套函数的递归调用中的 UnboundLocalError [重复]
【发布时间】:2012-08-14 00:00:14
【问题描述】:

我有以下 Python 代码:

def find_words(letters):
    results = set()

    def extend_prefix(w, letters):
        if w in WORDS: results.add(w)
        if w not in PREFIXES: return
        for L in letters:
            result = extend_prefix(w + L, letters.replace(L, "", 1))
            results = results | result

    extend_prefix('', letters)
    return results

print find_words("ABCDEFGH")

当我运行它时,我收到以下错误:

Traceback (most recent call last):
  File "ExtendPrefix.py", line 44, in <module>
    print find_words("ABCDEFGH")
  File "ExtendPrefix.py", line 41, in find_words
    extend_prefix('', letters)
  File "ExtendPrefix.py", line 38, in extend_prefix
    result = extend_prefix(w + L, letters.replace(L, "", 1))
  File "ExtendPrefix.py", line 38, in extend_prefix
    result = extend_prefix(w + L, letters.replace(L, "", 1))
  File "ExtendPrefix.py", line 35, in extend_prefix
    if w in WORDS: results.add(w)
UnboundLocalError: local variable 'results' referenced before assignment

在对extend_prefix 的递归调用中显然找不到结果。为什么会这样,我该如何解决?

【问题讨论】:

    标签: python recursion nested-function


    【解决方案1】:

    因为您在嵌套函数内分配结果,Python 假定您使用的是本地范围的变量,并在第 35 行抛出,即使它是更高范围内的有效名称。如果您只是读取变量而不写入它,它通常会在更高的命名空间对象上工作。但是一旦出现赋值运算符,就会跳转到本地命名空间。

    来自Python scopes/namespaces

    Python 的一个特殊之处在于——如果没有全局语句在 效果 - 对名称的赋值总是进入最内部的范围。 赋值不会复制数据——它们只是将名称绑定到对象。

    要解决这个问题,最简单的方法是将要使用的变量传递到函数头中:

    def extend_prefix(w, letters, results):
            if w in WORDS: results.add(w)
            if w not in PREFIXES: return
            for L in letters:
                extend_prefix(w + L, letters.replace(L, "", 1), results)
    

    同样你编写函数的方式,你没有返回一个集合,所以results = results | result 会被炸毁,结果是 None 类型。

    【讨论】:

      【解决方案2】:

      或者,如果您对结果使用默认值 None,然后将结果初始化为空集,则不需要嵌套函数。它简化了您的代码并解决了您的问题。见下文...

      def find_words(letters, pre = '', results = None):
          if results is None: results = set()
          if pre in WORDS: results.add(pre)
          if pre in PREFIXES:
              for L in letters:
                  find_words(letters.replace(L, '', 1), pre+L, results)
          return results
      

      很高兴在 StackOverflow 上看到另一个 Udacity 学生!

      【讨论】:

      • 我意识到我不应该在遛狗时设定结果。下次我应该在发布问题之前先遛狗!
      • 我以前做过很多次同样的事情。在电脑屏幕前几个小时后,我通常只需要休息一下来处理我一直在学习的东西:)
      猜你喜欢
      • 2021-05-10
      • 2022-01-22
      • 2015-02-13
      • 2014-08-07
      • 2021-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-27
      相关资源
      最近更新 更多