2017-02-21 26 views
2

Я новичок в python, и мне было интересно, могу ли я сгенерировать серию фибоначчи, используя функцию распознавания списка 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

Вы не можете это сделать так как понимание * списка * оценивается до того, как оно добавлено в 'series' ... –

+0

' reduce' - лучший выбор для серии фибоначчи, поскольку вход итерации X зависит от выхода итерации X -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)]

Обратите внимание, что мы здесь не добавляем результат в серию. Понимание списка используется только так, что .append вызывается на series. Однако некоторые из них учитывают понимание списков с побочными эффектами, а не склонными к ошибкам: он не очень декларативный и имеет тенденцию вводить ошибки, если их не делать осторожно.

+0

Понял. Большое спасибо! – PythonNewBie

1

Чтобы построить на том, что Виллем ван Onsem сказал:

Традиционный способ расчета п-й член последовательности Фибоначчи является просуммировать n-1 и n-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) 

Когда вам нужен потенциально бесконечный набор элементов, которые, возможно, следует рассмотреть либо function с одним или несколькими yield заявления или выражения генератора. Мне бы хотелось, чтобы числа Фибоначчи были с выражением генератора, но, по-видимому, нельзя.

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]