What is a "yield" statement in a function?
Possible Duplicate:
The Python yield keyword explained
Can someone explain to me what the yield statement actually does in this bit of code here:
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a+b
for number in fibonacci()
: # Use the generator as an iterator; print number
What I understand so far is, we are defining a function finonacci()
, with no parameters? inside the function we are defining a
and b
equal to 0 and 1, next, while this is true, we are yielding a
. What is this actually doing? Furthermore, while yielding a
? a
is now equal to b
, while b
is now equal to a + b
.
Next question, for number in fibonacci()
, does this mean for every number in the function or what? I'm equally stumped on what yield and 'for number' are actually doing. Obviously I am aware that it means for every number in fibonacci()
print number. Am I actually defining number without knowing it?
Thanks, sorry if I'm not clear. BTW, it's for project Euler, if I knew how to program well this would be a breeze but I'm trying to learn this on the fly.
Using yield
makes the function a generator. The generator will continue to yield the a
variable on each loop, waiting until the generator's next()
method is called to continue on to the next loop iteration.
Or, until you return
or StopIteration
is raised.
Slightly modified to show use of 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
>>>
Generators have a special property of being iterables which do not consume memories for their values.
They do this by calculating the new value, when it is required while being iterated.
ie
def f():
a = 2
yield a
a += 1
for ele in f():
print ele
would print
2
So you are using a function as an iterable that keeps returning values. This is especially useful when you require heavy memory usage, and so you cannot afford the use of a list comprehension
ie
li = [ele*10 for ele in range(10)]
takes 10 memory spaces for ints as a list
but if you simple want to iterate over it, not access it individually
it would be very memory efficient to instead use
def f():
i=0
while i<10
yield i*10
i += 1
which would use 1 memory space as i keeps being reused
a short cut for this is
ge = (i*10 for i in range(10))
you can do any of the following
for ele in f():
for ele in li:
for ele in ge:
to obtain equivalent results
When the code calls fibonacci
a special generator object is created. Please note, that no code gets executed - only a generator object is returned. When you are later calling its next
method, the function executes until it encounters a yield
statement. The object that is supplied to yield
is returned. When you call next
method again the function executes again until it encounters a yield
. When there are no more yield
statements and the end of function is reached, a StopIteration
exception is raised.
Please note that the objects inside the function are preserved between the calls to next
. It means, when the code continues execution on the next loop, all the objects that were in the scope from which yield
was called have their values from the point where a previous next
call returned.
The cool thing about generators is that they allow convenient iteration with for
loops. The for loop obtains a generator from the result of fibonacci
call and then executes the loop retrieving elements using next
method of generatior object until StopIteration
exception is encountered.
上一篇: python 2.7有什么收益?
下一篇: 什么是函数中的“yield”声明?