如何使用Python的列表推导创建斐波纳契系列?

时间:2017-02-21 14:44:41

标签: python list-comprehension fibonacci

我是python的新手,我想知道我是否可以使用python的列表推导功能生成斐波纳契系列。我不知道列表推导是如何实现的。 我尝试了以下(目的是生成前五个斐波那契数字):

series=[]
series.append(1)
series.append(1)
series += [series[k-1]+series[k-2] for k in range(2,5)]

这段代码抛出错误:IndexError: list index out of range

让我知道是否有可能使用列表理解来生成这样的系列。

8 个答案:

答案 0 :(得分:5)

您不能这样做:列表理解首先评估,然后将该列表添加到series。所以基本上就像你会写的那样:

series=[]
series.append(1)
series.append(1)
temp = [series[k-1]+series[k-2] for k in range(2,5)]
series += temp

然而,您可以使用 list comprehension 作为强制副作用的方法来解决此问题,例如:

series=[]
series.append(1)
series.append(1)
[series.append(series[k-1]+series[k-2]) for k in range(2,5)]

请注意,我们不会将结果添加到系列。列表理解仅用于在.append上调用series。然而,有些人认为列表理解有副作用而不容易出错:它不是很具说明性,如果不仔细的话,往往会引入错误。

答案 1 :(得分:3)

如果你知道你需要多少个系列术语,那么你可以紧凑地编写代码而不需要像这样的列表理解。

def Fibonacci(n):
    f0, f1 = 1, 1
    for _ in range(n):
        yield f0
        f0, f1 = f1, f0+f1

fibs = list(Fibonacci(10))
print (fibs)

如果您想要一些无限数量的术语,那么您可以使用它,这非常相似。

def Fibonacci():
    f0, f1 = 1, 1
    while True:
        yield f0
        f0, f1 = f1, f0+f1

fibs = []
for f in Fibonacci():
    fibs.append(f)
    if f>100:
        break
print (fibs)

当您需要可能无限的项目集合时,您应该考虑使用function一个或多个yield语句或生成器表达式。我希望能够用生成器表达式制作斐波那契数字但显然不能用。

答案 2 :(得分:3)

我们可以把它写成一个干净的Python列表理解(或生成器),使用它与黄金比例的关系:

>>> series = [int((((1 + 5**0.5) / 2)**n - ((1 - 5**0.5) / 2)**n) / 5**0.5) for n in range(1, 21)]
>>> series
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
>>> 

或更好一点:

>>> square_root_of_five = 5**0.5
>>> Phi = (1 + square_root_of_five) / 2
>>> phi = (1 - square_root_of_five) / 2
>>> 
>>> series = [int((Phi**n - phi**n) / square_root_of_five) for n in range(1, 21)]
>>> series
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]

答案 3 :(得分:2)

以Willem van Onsem所说的为基础:

计算斐波纳契数列第n项的传统方法是将n-1n-2项加在一起,如您所知。列表理解旨在创建一个在理解过程中没有副作用的列表(除了创建单个列表)。在计算序列期间存储序列的最后2个项是副作用,因此列表理解不适合任务本身。

一个安全的方法是创建一个闭包生成器(本质上是一个具有一些相关私有状态的生成器),它可以传递给列表理解,这样列表理解就不必担心存储内容的细节了。 :

def fib_generator(n):

    def fib_n_generator():
        last = 1
        curr = 1

        if n == 0:
            return

        yield last
        if n == 1:
            return

        yield curr
        if n == 2:
            return

        ii = 2
        while ii < n:
            next = curr + last
            yield next
            last = curr
            curr = next
            ii += 1

    return fib_n_generator()

fib = [xx for xx in fib_generator(10)]
print(fib)

答案 4 :(得分:1)

使用赋值表达式(python> = 3.8):

s = [0, 1]
s += [(s := [s[1], s[0] + s[1]]) and s[1] for k in range(10)]

print (s)
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

答案 5 :(得分:0)

基于显式公式 1 的斐波那契系列的列表推导式:

[int((0.5+5**0.5/2)**n/5**0.5+0.5) for n in range(21)]

答案 6 :(得分:0)

这是一个单行列表推导式解决方案,它避免了使用嵌套 ternary operatorswalrus operator 的单独初始化步骤(因此需要 Python 3.8),并且还避免了 explicit formexplicit form 的快速发生溢出问题{3}} 可以为您提供(及其 **n 组件):

[
    0 if not i else
        (x := [0, 1]) and 1 if i == 1 else
            not x.append(x[-2] + x[-1]) and x[-1]
    for i in range(10)
]

给出:

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

这比生成最多 N 的所有值的 enter image description here 更快。但是,如果您不想要所有值,那么显式形式可能会快得多,但它确实会受到影响1000 到 2000 之间的一些 N 溢出:

n = 2000
int((((1 + 5**0.5) / 2)**n - ((1 - 5**0.5) / 2)**n) / 5**0.5)

给我:

OverflowError: (34, 'Numerical result out of range')

而“添加最后两个值”的方法可以为较大的 N 生成更高的值。在我的机器上,我可以继续使用直到内存耗尽之前的 N 介于 300000 和 400000 之间。

感谢乔纳森·格雷戈里 (Jonathan Gregory) 带领我走向了这种方法。

答案 7 :(得分:-1)

使用列表理解:

n = int(input())
fibonacci_list = [0,1]
[fibonacci_list.append(fibonacci_list[k-1]+fibonacci_list[k-2]) for k in range(2,n)]

if n<=0:
   print('+ve numbers only')
elif n == 1:
   fibonacci_list = [fibonacci_list[0]]
   print(fibonacci_list)
else:
   print(fibonacci_list)

也许是解决这个问题的可行方法...