私はPythonを初めて使用しますが、Pythonのリスト内包表記機能を使用してフィボナッチ数列を生成できるかどうか疑問に思っていました。リスト内包表記がどのように実装されているのかわかりません。私は次のことを試みました(意図は最初の5つのフィボナッチ数を生成することでした):
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
。
リスト内包を使用してそのようなシリーズを生成することさえ可能かどうか教えてください。
そのようにすることはできません:リスト内包は最初に評価されます、そしてそのリストは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)]
ここで注意してください結果をシリーズに追加しないでください。リスト内包表記は、.append
はseries
で呼び出されます。ただし、エラーが発生しやすい副作用を伴うリスト内包表記を検討する人もいます。これは宣言型ではなく、注意深く行わないとバグが発生する傾向があります。
必要なシリーズの用語がいくつあるかがわかっている場合は、このようなリスト内包表記なしでコードをコンパクトに記述できます。
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)
アイテムの潜在的に無限のコレクションが必要な場合は、1つ以上のfunction
ステートメントを含むyield
またはジェネレーター式のいずれかを検討する必要があります。ジェネレータ式でフィボナッチ数を作成できるようにしたいと思いますが、どうやらできません。
黄金比との関係を使用して、クリーンな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]
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)
リスト内包表記の使用:
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)
多分それはこの問題の実行可能な解決策です...