我是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 :(得分: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-1
和n-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 operators 和 walrus operator 的单独初始化步骤(因此需要 Python 3.8),并且还避免了 explicit form 和 explicit 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 的所有值的 更快。但是,如果您不想要所有值,那么显式形式可能会快得多,但它确实会受到影响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)
也许是解决这个问题的可行方法...