【问题标题】:Python: clean up my list for reuse (fibonacci example)Python:清理我的列表以供重用(斐波那契示例)
【发布时间】:2016-02-15 01:58:43
【问题描述】:

所以我试图证明产生斐波那契数的递归方法非常低效,我使用列表因为它们是通过引用调用的,因此一旦函数拆分,它们仍然会更改相同的变量。问题:完成后我不知道如何清理列表。这导致了一个问题,即在我们的列表中第一次运行时需要从 1 到 5,但在第二次运行时从 6 到 10 开始。

# Iterative method has exactly n repetitions
# let's compare recursive method:
def fiborec(n, i = []):
    i.append(len(i)+1)
    print('this is call nr.:', len(i))

    if n == 0:
        return 0
    elif(n == 1):
        return 1
    else:
        return fiborec(n - 1, i) + fiborec(n - 2, i)

我也试过了:

def fiborec(n, i = [0]):
    i[0] += 1
    print('this is call nr.:', i[0])

两种方法都表现出相同的行为 :( 这让我想到,i = [0] 没有被使用,因为引用已经存在。

del i[:] 不起作用,因为我们有两个结束条件,所以没有明确的结束,所以添加它的地方有点不清楚 - 至少对我来说。

所以...我的临时修复:

def fiborec(n):
    """Docstring: returns Fibonacci Number for given Int. 

recursive method

"""
    i = [0] # we want i to be "passed by reference" due to lots of function calls
            # but also to be resetted should we reuse the function
    return _fiborecursion(n, i)

我不喜欢它,但这是我现在能想到的最好的 D: 如果有人有我不需要两个功能的解决方案,请告诉我们^_^

【问题讨论】:

  • 使用i=None作为默认值,然后在第一次调用函数时检查if i is None: i = []。这是避免此问题的典型方法 (stackoverflow.com/q/1132941/3001761)。或者将 memoization 实现为装饰器。
  • 好吧,我现在决定创建一个运行一次的函数,只是为了重置计数器,然后调用递归函数......在我看来并不漂亮,但我能想到的最好的。不过,我一定会通读链接。 TY

标签: python list recursion pass-by-reference


【解决方案1】:

我相信@jonrsharpe 的建议会解决你原来的问题:

def fiborec(n, i=None):
    if i is None:
        i = [1]
    else:
        i.append(len(i) + 1)
    print('this is call nr.:', i[-1])

    if n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fiborec(n - 1, i) + fiborec(n - 2, i)

fiborec(10)生成:

('this is call nr.:', 1)
('this is call nr.:', 2)
('this is call nr.:', 3)
('this is call nr.:', 4)
('this is call nr.:', 5)
...
('this is call nr.:', 173)
('this is call nr.:', 174)
('this is call nr.:', 175)
('this is call nr.:', 176)
('this is call nr.:', 177)
55

但是可以再次调用(没有第二个参数)而没有副作用。

但是,如果你确实是:

试图证明产生斐波那契数的递归方法 效率很低

公平竞争并使用高效的递归斐波那契解决方案:

def fibofast(n, res=0, nxt=1, i=None):
    if i is None:
        i = [1]
    else:
        i.append(len(i) + 1)
    print('this is call nr.:', i[-1])

    if n == 0:
        return res
    return fibofast(n - 1, nxt, res + nxt, i)

fibofast(10)生成:

('this is call nr.:', 1)
('this is call nr.:', 2)
('this is call nr.:', 3)
('this is call nr.:', 4)
('this is call nr.:', 5)
('this is call nr.:', 6)
('this is call nr.:', 7)
('this is call nr.:', 8)
('this is call nr.:', 9)
('this is call nr.:', 10)
('this is call nr.:', 11)
55

【讨论】:

    猜你喜欢
    • 2013-08-03
    • 2013-02-24
    • 1970-01-01
    • 2014-05-23
    • 2018-07-03
    • 2014-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多