nobody
nobody

Reputation: 8263

Python yield vs Ruby yield

In Ruby, the yield keyword is used to yield to closures for blocks of execution.

How does this keyword differ in the Python language?

Upvotes: 15

Views: 3744

Answers (2)

Ze Gao
Ze Gao

Reputation: 91

In Ruby, yield is used to bounce control to block( like anonymous function) to execute the block's statements and then bounce back to where the block's called.

With yield args you can pass arguments to the block, and also with lvar = yield you can get whatever returned and bind it to lvar after control exits the block. It's a much general and consistent feature design in Ruby. And of course, you can apply this idea to iterating over collections.

Whereas in Python, mostly people use yield to facilitate effective access of items over somewhat collection, they focus on iterate once and generate on the fly once being called idea, which is the main use of yield in Python.

FYI, It's not quite a distinguished feature between Python and Ruby on yield, at least on the way to use it. (Apparently they are implemented differently, as for python, yield creates a generator, which will not run any code unless the iteration starts). For example, the way yield is used in python contextmanager is quite the same in Ruby.

from contextlib import contextmanager
@contextmanager
def openfile(name, mode):
    f= open(name, mode)
    yield f
    f.close()

with openfile('log.txt', 'r') as handle:
    for line in handle:
        print line

here, yield pass file handle to with, and execute with-statements exactly once and then bounce back to file close statement

Upvotes: 1

7stud
7stud

Reputation: 48599

In ruby, yield is a shortcut that is used to call an anonymous function. Ruby has a special syntax for passing an anonymous function to a method; the syntax is known as a block. Because the function has no name, you use the name yield to call the function:

def do_stuff(val)
  puts "Started executing do_stuff"
  yield(val+3)
  yield(val+4) 
  puts "Finshed executing do_stuff" 
end

do_stuff(10) {|x| puts x+3} #<= This is a block, which is an anonymous function
                            #that is passed as an additional argument to the 
                            #method do_stuff

--output:--
Started executing do_stuff
16
17
Finshed executing do_stuff

In python, when you see yield inside a function definition, that means that the function is a generator. A generator is a special type of function that can be stopped mid execution and restarted. Here's an example:

def do_stuff(val):
    print("Started execution of do_stuff()")

    yield val + 3
    print("Line after 'yield val + 3'")
    yield val + 4
    print("Line after 'yield val + 4'")

    print("Finished executing do_stuff()")


my_gen = do_stuff(10)

val = next(my_gen)    
print("--received {} from generator".format(val))

output:

Started execution of do_stuff()
--received 13 from generator

More code:

val = next(my_gen)    
print("--received {} from generator".format(val))

output:

Line after 'yield val + 3'
--received 14 from generator

From the output, you can see that yield causes a result to be returned; then execution is immediately halted. When you call next() again on the generator, execution continues until the next yield statement is encountered, which returns a value, then execution halts again.

Upvotes: 20

Related Questions