【问题标题】:Having trouble with this recursive function这个递归函数有问题
【发布时间】:2014-07-11 21:55:24
【问题描述】:

参见下面的函数。我想要做的是获取我发送的任何字符串,搜索“[”和“]”字符。如果它们存在,这部分文本将被拆分,括号被删除并变成一个字典。然后,我尝试将 dict 中的任何值匹配到 attrs 列表。如果匹配,则将该值插入回原始字符串,然后我们使用新字符串再次调用该函数。条件然后检查是否有更多的括号,如果没有,则返回新的字符串。

但是当我运行代码时,我为 text1 返回的值是 None。我将 print 语句放在 else 子句中,以查看那里发生了什么,并且按预期打印了新字符串,但是该字符串没有在 return 语句中传回。

当我使用 text2 调用函数时,它与我期望 text1 保存的字符串相同,该值确实是分配给 string2 的原始字符串。

import ast

string1 = "Lorem ipsum dolor sit amet, consectetur adipisicing elit [{'do':'said', 'eiusmod':'tempor', 'incididun':'ut'}]"

string2 = "Lorem ipsum dolor sit amet, consectetur adipisicing elit"



def formatter(content):
    if content.find('[') >= 0:
        attrs = ['do', 'fum']
        ind, indend = content.find('['), content.find(']')
        choice = ast.literal_eval(content[ind+1:indend])
        for attr in attrs:
            for key, value in choice.iteritems():
                if attr == key:
                    new_choice = choice[key]
                    new_string = content[:ind] + new_choice + content[indend+1:]
                    formatter(new_string)
    else:
        return content

text1 = formatter(string1)
text2 = formatter(string2)
print text1
print text2

【问题讨论】:

  • 一些一般建议:content.find('[') >= 0 很难看,请改用'[' in content。另外,不要滥用元组拆包。将 indindend 分配移动到单独的行中。最终,如果您最终使循环的整个主体成为条件,最好使用if not condition: continue 以避免实际主体的额外缩进级别。即使您使用 100 或 120 个字符的行,水平空间也很有价值!

标签: python


【解决方案1】:

我已经稍微调整了你的代码,以便更清楚地了解正在发生的事情:

import ast

string1 = "Lorem ipsum dolor sit amet, consectetur adipisicing elit [{'do':'said', 'eiusmod':'tempor', 'incididun':'ut'}]"

string2 = "Lorem ipsum dolor sit amet, consectetur adipisicing elit"



def formatter(content):
    print "content: %s" % content
    if content.find('[') >= 0:
        print "running if"
        attrs = ['do', 'fum']
        ind, indend = content.find('['), content.find(']')
        choice = ast.literal_eval(content[ind+1:indend])
        for attr in attrs:
            for key, value in choice.iteritems():
                if attr == key:
                    new_choice = choice[key]
                    new_string = content[:ind] + new_choice + content[indend+1:]
                    print "calling formatter with: %s" % new_string
                    formatter(new_string)
                    print "back from recursion"
    else:
        print "running else"
        print content
        return content

print "string1"
print formatter(string1)
print "string2"
print formatter(string2)

如果您查看输出,您会看到在第一遍中找到了[,因此我们进入if 子句。 attr == key在一种情况下被发现为真,所以我们下降到内部if子句,然后触发对formatter(new_string)的递归调用

在该调用中,没有[,因此content 被返回到格式化程序的原始运行......在那里它被丢弃,因为对formatter() 的递归调用的输出没有分配给任何东西。

循环最终结束,执行结束,函数没有返回任何内容。

如果您想冒泡content 备份调用堆栈,则必须从递归调用中捕获返回并对其进行处理。您最终需要将其返回,但如果您想捕获所有匹配项,则需要在迭代 attrs 时创建一个返回值列表,然后在最后返回整个列表。

【讨论】:

  • 使用 text1 我用 string1 调用函数。因此,第一次通过函数时,if 子句将触发,括号将从字符串中删除,然后使用新字符串 formatter(new_string) 再次调用该函数。新字符串(在这种情况下)没有任何括号,因此触发 else 子句。 if 子句没有 return 语句的原因是我希望它继续运行 if 子句,直到删除所有括号。
  • 哦,看,这个函数是递归的,所以你会期望它再次触发。
  • 啦啦啦。我现在已经更好地阅读了代码。问题实际上是您的attrs 列表与字典中的任何键都不匹配,因此if attr == key 中的块永远不会运行。
  • 哎呀。我已经更改了这篇文章的原始代码中的字符串,但忘记更改 attrs。现在更新了,我的问题依然存在。
  • 所以,我已经通过使用 return formatter(new_string) 来完成这项工作,而不仅仅是调用 formatter(new_string)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-27
  • 1970-01-01
  • 1970-01-01
  • 2020-03-21
  • 1970-01-01
  • 2015-01-27
  • 1970-01-01
相关资源
最近更新 更多