Что такое выражение "выход" в функции?
Возможный дубликат:
Откроется ключевое слово 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
.