欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Yield in Python/Ruby - Iterator/Visitor 博客分类: Design RubyPython虚拟机CC++ 

程序员文章站 2024-03-18 20:54:46
...
Yield in Python/Ruby - Iterator/Visitor

首先,我们从Ruby的Iterator开始。Ruby程序员可以用yield关键字定义Iterator。例如,下面的abc()就是一个Iterator。

def abc()
yield “a”
yield “b”
yield “c”
end

abc Iterator的调用方法如下:

# block形式
abc do | ch |
print ch
end

或者
# closure形式
abc { | ch | print ch }

从这个调用方式,我们可以看出,实际上,Ruby Iterator并不是真正的Iterator,而是一个Visitor。Yield其实只是一个占位符。上述Ruby Iterator代码的真实含义如下:

def abc( visitor )
visitor.visit( “a” )
visitor.visit( “b” )
visitor.visit( “c” )
end

调用方法为

class Printer
def visit( ch )
print ch
end
end

abc( Printer.new )

我们看到,Ruby “Yield” Iterator只是一种虚拟Iterator,虽然貌似Iterator,其实却是Visitor。我们无法中途中断abc()的执行。只能从头到尾打印出abc。
Python “Yield” Iterator是真正的Iterator,例如:

def abc() :
yield “a”
yield “b”
yield “c”

调用方法为

for ch in abc()
if ch == “b”
break
print ch

我们看到,abc()确实返回了一个Iterator,而且我们可以中途中断程序,只打印出ab。
Python Iterator是采用coroutine实现的。
Coroutine表示几个协同工作的程序。比如,消费者/生产者,你走几步,我走几步;下棋对弈,你一步我一步。人们就很容易想到用Coroutine来实现Iterator。
这里面Iterator就是Coroutine里面的生产者Producer角色,数据提供者。所以,也叫做Generator。
每次Iterator程序就是等在那里,一旦用户(消费者Consumer角色)调用了iterator.next, Iterator就继续向下执行一步,然后把当前遇到的内部数据的Node放到一个消费者用户能够看到的公用的缓冲区(比如,直接放到消费者线程栈里面的局部变量)里面,然后自己就停下来(wait)。然后消费者用户就从缓冲区里面获得了那个Node。
这样Iterator就可以自顾自地进行递归运算,不需要自己管理一个栈,而是迫使计算机帮助它分配和管理运行栈。

Python “Yield” Iterator可以实现无限数据的Iterator。
def infinite()
n = 1
while true
yield n
n = n + 1

调用方法
for i in infinit()
if i > 100
break

print i