python(23): 发生器和循环器(14.6)
时间:2006-03-31 来源:newsim
好久没有看书了。先是“两会”开了,我也像代表委员们一样忙,没有心情写。后来又是人一贯的惰性在起作用。以至于到了月底了,才觉得应该再看看书。还好对于是月份来说也算是有始有终。
发生器函数其实也是一种函数,用def来定义。当然跟一般的函数是不一样的。首先,普通函数既可以用def来定义,也可以用lambda来定义。而“发生器函数”应该只能用def来定义。其次,一般的函数在被调用的时候会用return语句返回一个值,然后退出。而发生器在被调和的时候,会返回一个叫做“发生器”类型的对象。
现在想象一下,用def定义了一个函数。那么,解释器怎么知道这是一个发生器函数呢。其实也很简单,一个发生器函数必然会包含一个或多个yield语句,当解释器碰到这样的函数时,就会知道这是一个“发生器函数”。下面通过一个简单的例子来了解具体的运行情况:
在上面的例子中,我们使用了next方法来显式地控制“发生器函数”一个一个地“发生”值。其实发生器函数更多的时候是用在”循环“的语境中,比如for语句、map()函数、list再构造等。当使用在这些语句中时,并不需要显式地调用next方法。 比如:
下面来说说”循环器“。循环器也是一种对象,它由内置于函数iter()产生。这种对象也有一个next方法。作用与”发生器“对象中的next相同。由于在python中,一切皆对象。比如D为一个dict,iter(D)实际上只是调用了D中的__iter__函数。所以,如果自己定义一个类,只要这个类有__iter__函数,能产生”循环器“对象,那么这个类的对象就完全可以使用在像for语句这样的循环语境中。
最后说一句,发生器实际达的效果是返回一组值。这种功能可以使用return语句返回一个序列(list dict tuple)来实现。但是如果当这个序列太大时,相信用”发生器“是一个更好的选择。因为,这样的话就没有必要把一大堆的东西放到内存中。
发生器函数其实也是一种函数,用def来定义。当然跟一般的函数是不一样的。首先,普通函数既可以用def来定义,也可以用lambda来定义。而“发生器函数”应该只能用def来定义。其次,一般的函数在被调用的时候会用return语句返回一个值,然后退出。而发生器在被调和的时候,会返回一个叫做“发生器”类型的对象。
现在想象一下,用def定义了一个函数。那么,解释器怎么知道这是一个发生器函数呢。其实也很简单,一个发生器函数必然会包含一个或多个yield语句,当解释器碰到这样的函数时,就会知道这是一个“发生器函数”。下面通过一个简单的例子来了解具体的运行情况:
- def gen(x):
- for i in range(x)[2:]:
- yield i
- yield i**2
- x = gen(5)
- x.next()===>2
- x.next()===>4
- x.next()===>3
在上面的例子中,我们使用了next方法来显式地控制“发生器函数”一个一个地“发生”值。其实发生器函数更多的时候是用在”循环“的语境中,比如for语句、map()函数、list再构造等。当使用在这些语句中时,并不需要显式地调用next方法。 比如:
- for i in x:
- print i
下面来说说”循环器“。循环器也是一种对象,它由内置于函数iter()产生。这种对象也有一个next方法。作用与”发生器“对象中的next相同。由于在python中,一切皆对象。比如D为一个dict,iter(D)实际上只是调用了D中的__iter__函数。所以,如果自己定义一个类,只要这个类有__iter__函数,能产生”循环器“对象,那么这个类的对象就完全可以使用在像for语句这样的循环语境中。
最后说一句,发生器实际达的效果是返回一组值。这种功能可以使用return语句返回一个序列(list dict tuple)来实现。但是如果当这个序列太大时,相信用”发生器“是一个更好的选择。因为,这样的话就没有必要把一大堆的东西放到内存中。
相关阅读 更多 +