2017-02-21 323 views
2

我是新来的蟒蛇,我想知道如果我可以使用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

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

+0

你不能做到这一点就像那样,因为*列表理解*在被添加到“系列”之前被评估为拳头...... –

+0

由于迭代X的输入取决于迭代X的输出,所以'reduce'是斐波那契数列的更好选择-1 –

回答

4

你不能那样做:在列表理解评估第一,然后将该列表添加到series。所以基本上它会像你会写:

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

但是,您可以通过使用列表理解作为一种力的副作用,例如像解决这个问题:

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

请注意,我们在这里不会将结果添加到系列。列表理解仅用于在series上调用.append。但是有些人认为带有副作用的列表理解比较容易出错:它不是非常具有说明性,并且如果不仔细地做,往往会引入错误。

+0

了解。非常感谢你! – PythonNewBie

1

要建立在什么威廉·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) 
2

如果你知道你有多少的一系列条款需要,那么你可以紧凑地写代码,而列表的理解是这样的。

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) 

当你需要的物品的一个潜在的无限集合,你或许应该考虑或者与一个或多个yield陈述或发电机表达function。我希望能够使用生成器表达式来生成斐波那契数列,但显然不能。

2

我们可以使用它的黄金比例关系,它写成一个干净的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]