Python yield vs Ruby yield

15
在Ruby中,yield关键字用于向执行块的闭包屈服。
在Python语言中,这个关键字有所不同吗?

4
我会回答,但我认为this已经涵盖了它。 - Alex
2个回答

20
在 Ruby 中,yield 是用于调用匿名函数的快捷方式。Ruby 有一种特殊的语法来将匿名函数传递给方法;该语法称为“块”。因为该函数没有名称,所以您使用名称 yield 来调用该函数:
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

在Python中,当您在函数定义内部看到yield时,这意味着该函数是一个生成器。生成器是一种特殊类型的函数,可以在执行过程中停止并重新启动。以下是一个示例:

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))

输出:

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

更多代码:

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

输出:

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

从输出结果可以看出,yield导致返回一个结果;然后立即停止执行。当你再次在生成器上调用next()时,执行将继续,直到遇到下一个 yield 语句,该语句返回一个值,然后执行再次停止。


9
基本上,Python中的yield关键字相当于Ruby中的Enumerator::Yielder#yield - Jörg W Mittag
谢谢!我不知道 Enumerator::Yielder 类!! - nobody
2
关于 Enumerator::YielderEnumerator::Generator 的更多细节,我建议参考:http://patshaughnessy.net/2013/4/3/ruby-2-0-works-hard-so-you-can-be-lazy - Alex Moore-Niemi

1
在Ruby中,yield用于将控制权传递给块(类似于匿名函数)以执行块的语句,然后返回到调用块的位置。通过使用yield args,您可以向块传递参数,并且使用lvar = yield可以在控制退出块后将其绑定到lvar。这是Ruby中更通用和一致的特性设计。当然,您也可以将此想法应用于对集合进行迭代。
而在Python中,大多数人使用yield来促进对某种集合项的有效访问,他们专注于迭代一次并在被调用时实时生成的思想,这是Python中yield的主要用途。
顺便说一下,在yield方面,Python和Ruby之间并没有明显的区别,至少在使用方式上是如此。(显然它们的实现方式不同,因为对于Python,yield创建一个生成器,除非迭代开始,否则不会运行任何代码)。例如,在Ruby中,yield在上下文管理器中的使用方式与Python中相同。
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

在这里,yield文件句柄传递给with,并且执行with语句块恰好一次,然后返回到文件关闭语句。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接