尝试直至没有异常?

3
def foo():
    try:
        html = get(url)
        while (html is nogood):
            foo()
        return html
    except Exception as e:
        changeip()
        foo()

函数foo返回纯文本的良好HTML内容。
但是,当捕获到Exception时,该函数有时会返回None
因此,我将最后一行更改为return foo(),并按预期工作。
问题是为什么?在捕获中,它只是再次调用foo,最终会返回良好的HTML文本,为什么我要加上额外的return
谢谢。
3个回答

2

您根本不需要递归解决方案。在foo中,只需循环直到获得良好的HTML。每次循环后,做一些事情来提高获取良好HTML的机会(changeip是否适用于此目的?)。

def foo():
    while True:
        try:
            html = get(url)
            if is_good(html):
                return html
        except Exception:  # Need specific exception, do not catch all
            changeip()

changeip确实有效,它使用Tor。感谢您对代码的改进。 - taesu

1

想一想,如果第一个foo()失败了,它会返回什么。

main调用foo1并且它失败了 -> foo1调用foo2并且它成功了 -> foo2将html返回给foo1 -> 在foo1中没有其他代码需要执行,因此它返回None

foo最终成功时,它不会将html返回给main,而是返回给最后一个调用者,这种情况下是foo1

问题在于,在第一个foo调用失败后,您正在丢弃任何foo调用的结果。您需要通过最后一行将html沿着链返回到return foo(),就像您提到的那样。


我非常确定这不是问题所在。你确定那一行代码有被执行到吗?如果 html = get(url) 执行成功,那么 while 循环就不会被执行,而如果失败,则异常会被调用对吗? - Loocid

1
想象一个大纸箱,放在房间中心。这个箱子代表你的函数foo。现在,让我们将return的含义改为类似于change_this_boxes_colour。无论箱子颜色变成什么(实际上就是返回值),都可以从你当前所在的房间看出来。这就是函数提供信息的方式。
现在,在这个大纸箱里面有一些神奇的东西,因为它可以创建自己的小盒子(包括它自己的副本!)。现在,让我们看一些代码,并用盒子的术语来思考它:
def bar():
    return BLUE  # every `bar` box turns `BLUE`

def foo():
    bar()

print(foo())  # prints None

这是一个简单的代码,我们在函数内部调用了另一个函数,但没有获取它的返回值(颜色)。

再次采用盒子思想,我们有一个大盒子(无颜色),位于房间中央。但是它自己在里面又创建了一个盒子(bar),这个盒子预期会变成蓝色。但 foo 没有设置颜色(返回值),因此它仍然是无色的。

我们仍然站在大的 foo 盒子外面,因此我们看不到 bar 盒子的颜色。如果我们想知道 bar 变成了什么颜色,就必须让 foo 告诉我们。这可以通过要求 foo 将自己设置为与它所看到的 bar 相同的颜色来实现。在这种情况下,是蓝色。

def bar():
    return "BLUE"  # every `bar` box turns "BLUE"

def foo():
    return bar()  # change our colour to the same colour as `bar`

print(foo())  # prints "BLUE"

在您的情况下,foo 会在其自己的盒子内创建其自身的版本,但原则仍然适用。

希望这可以解答您最初的问题,但是@hai-vu是正确的,递归不仅是不必要的,而且可以说是一个错误(因为Python有递归限制)。 - Harry Vane
感谢您的详细解释。现在很清楚了。 - taesu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接