Что такое выражение "выход" в функции?

Возможный дубликат:
Откроется ключевое слово yield Python

Может кто-нибудь объяснить мне, что на самом деле делает инструкция yield в этом бите кода:

 def fibonacci():
     a, b = 0, 1
     while True:
         yield a
         a, b = b, a+b

для числа в fibonacci(): # Использовать генератор в качестве итератора; номер печати

Насколько я понимаю до сих пор, мы определяем функцию finonacci() без параметров? внутри функции мы определяем a и b, равные 0 и 1, затем, в то время как это верно, мы получаем a. Что это на самом деле делает? Кроме того, давая a? a теперь равно b, а b теперь равно a + b.

Следующий вопрос, для числа в fibonacci(), означает ли это для каждого числа в функции или что? Я в равной степени ошеломлен тем, что доходность и "за число" на самом деле делают. Очевидно, что я знаю, что это означает для каждого числа в fibonacci() номере печати. Я действительно определяю номер, не зная об этом?

Спасибо, извините, если я не понимаю. Кстати, это для проекта Эйлера, если бы я знал, как правильно программировать, это будет легкий ветерок, но я пытаюсь изучить это на лету.

Ответы

Ответ 1

Использование yield делает функцию генератором. Генератор будет продолжать выдавать переменную a в каждом цикле, ожидая, пока не будет вызван метод генератора next(), чтобы продолжить переход к следующей итерации цикла.

Или, пока не будет поднят return или StopIteration.

Немного изменено, чтобы показать использование StopIteration:

>>> def fib():
...     a = 0
...     b = 1
...     while True:
...         yield a
...         a = b
...         b += a
...         if a > 100:
...             raise StopIteration
...
>>>
>>> for value in fib():
...     print value
...
0
1
2
4
8
16
32
64
>>>

>>> # assign the resulting object to 'generator'
>>> generator = fib()
>>> generator.next()
0
>>> generator.next()
1
>>> for value in generator:
...     print value
...
2
4
8
16
32
64
>>>

Ответ 2

Когда код вызывает fibonacci, создается специальный объект генератора. Обратите внимание, что никакой код не выполняется - возвращается только объект генератора. Когда вы позже вызываете свой метод next, функция выполняется до тех пор, пока не встретит оператор yield. Возвращается объект, который поставляется в yield. Когда вы снова вызываете метод next, функция выполняется снова, пока не встретится с yield. Если более выражений yield и конца функции не достигнуто, возникает исключение StopIteration.

Обратите внимание, что объекты внутри функции сохраняются между вызовами next. Это означает, что, когда код продолжает выполнение в следующем цикле, все объекты, которые были в области, из которой был вызван yield, имеют свои значения от точки, в которой был возвращен предыдущий вызов next.

Холодная вещь о генераторах заключается в том, что они позволяют удобную итерацию с циклами for. Цикл for получает генератор из результата вызова fibonacci, а затем выполняет элементы извлечения цикла с использованием метода next для генераторного объекта до тех пор, пока не будет встречено исключение StopIteration.

Ответ 3

Генераторы имеют особое свойство быть итерабельными, которые не потребляют воспоминания для своих значений.

Они делают это, вычисляя новое значение, когда оно требуется при повторении.

то есть.

def f():
    a = 2
    yield a
    a += 1

for ele in f():
    print ele

будет печатать

 2

Итак, вы используете функцию как итерабельную, которая сохраняет возвращаемые значения. Это особенно полезно, когда вам требуется интенсивное использование памяти, и поэтому вы не можете позволить себе использовать понимание списка.

то есть.

li = [ele*10 for ele in range(10)]

занимает 10 пространств памяти для ints в виде списка

но если вы просто хотите перебрать его, не получите доступ к нему индивидуально

было бы очень эффективно использовать память вместо

def f():
    i=0
    while i<10
        yield i*10
        i += 1

который будет использовать 1 ячейку памяти, поскольку я продолжаю использовать повторно

сокращение для этого

ge = (i*10 for i in range(10))

вы можете выполнить любое из следующих действий

for ele in f():

for ele in li:

for ele in ge:

для получения эквивалентных результатов

Ответ 4

Этот ответ является отличным объяснением оператора yield, а также итераторов и генераторов.

В частности, первый вызов fibonaci() будет инициализировать a до 0, b до 1, введите цикл while и верните a. Любой следующий вызов начнется после инструкции yield, повлияет на b на a, a+b на b, а затем перейдите к следующей итерации оператора while, снова верните оператор yield, и снова верните a.