[Tutor] Difference between 'yield' and 'print'

Luke Paireepinart rabidpoobear at gmail.com
Wed Jan 17 09:04:12 CET 2007


raghu raghu wrote:
> Is there any difference between yield and print in python script?i 
> have written a script based on fibonacci series where in i used yield 
> and print in two different scripts:
> the script is given below:
> def fib(n):
>     a,b = 0,1
>     while a<=n:
>        print a
>        a,b = b,a+b
>       
> for x in fib(4):
>     print  x. When i executed this script i am getting this error: 
> Typeerror:"nonetype" is not iterable
> But the same script if 'print' is replaced with 'yield' inside while 
> loop it is executing properly without any type errors
> could any one reply why print cant be used instead of yield and why 
> error is generated?


the version of the function you created, fib(n) with the print, takes an 
argument 'n' and outputs the fibonacci sequence.
It does not return anything.

'for x in fib(4):'
is equivalent to saying:
'for x in none:'
which doesn't work because you can't iterate over nothing.



Refer to http://docs.python.org/ref/yield.html for information about yield.
Disclaimer: The following information I'm going to present you I came up 
with after reading that short explanation of 'yield' so it may not be 
exactly correct.
Also, I didn't check any code samples to see if they executed correctly.  :)


The reason the script works with 'yield' is because the fib(n) function 
then becomes a generator function.
The way I understand it (I don't know that much about generators)

By saying

def some_function(n):
    a = 0
    while a <= n:
       yield a
       a += 1

and looping over (what you'd think would be ) the returned value of the 
function call
for x in some_function(5):
    print x

what's really happening is that, the first time the loop is run,
the body of some_function is executed, until it gets to the first 
'yield' statement.
this value is then yielded ('returned' in a sense) but the function 
object is not destroyed.
The yielded value is assigned to x.  after the body of the for loop 
executes,
the function object is resumed at the first 'yield'.
It's the same for every case, where it resumes execution at the last 
'yield' until there are no more values to yield.


So the first time through the 'for' loop,
a is set to 0
the inner while loop starts, a is < 5.
the value 0 is returned and bound to x
we print x

now the for loop starts over, some_function is resumed at where the 
'yield' was,
a is incremented, it's now 1
1 < 5, while loop starts again, the value of a (1) is returned.
etc, etc, etc.

until:
the for loop starts over, some_function is resumed where the 'yield' was,
a is incremented, it's now 6.
while loop repeats, a is not < n, the function ends, not returning a value.

so the end result is
012345

The basic idea, i think, is calling 'some_function(5)' creates a 
generator object (an instance of some 'generator' class?)
which has a method called next().

So you could think of the loop like this:
gen = some_function(5) #create the generator
while 1:
    try:
       print gen.next()
    except: #we ran out of things to generate (the generator stopped 
yielding results -- supposedly it raises an error here?)
       print "End of generator."
       break

Anyway, I've never used them but that sounds like a reasonable way for 
them to work.
If you'd like a better explanation you might poke around Alan Gauld's 
tutorial, he probably has a section on generators.

HTH,
-Luke


More information about the Tutor mailing list