一、说明return一直中,每中语言中其没没有很大差别,就不多说了。(shell语言return的是退出状态,可能差别是比较大的,感兴趣可参见“Linux Shell函数定义与调用”) Show 最早看到yield应该是哪们语言用来调整什么线程优先级的,记不清了,不过那里的yield和python中的yield应该功能有区别。 python中最早看到yield应该是使用scrapy框架写爬虫的时候,之前也有去看yiled的用法,总记不太住。今天又去看了一下,基本上来就是讲些斐波那契数列的烦的要死,自己写段程序研究了一下,这里记一下。 二、return和yield的异同共同点:return和yield都用来返回值;在一次性地返回所有值场景中return和yield的作用是一样的。 不同点:如果要返回的数据是通过for等循环生成的迭代器类型数据(如列表、元组),return只能在循环外部一次性地返回,yeild则可以在循环内部逐个元素返回。下边我们举例说明这个不同点。 三、实例说明3.1 return版本示例代码如下: class TestYield: def gen_iterator(self): result_list = [] for j in range(3): print(f"gen_iterator-{j}") result_list.append(j) # return在循环的外部,待变量完全生成后一次性返回 return result_list def call_gen_iterator(self): # 执行下边这句后result_list直接是完成的结果[0,1,2] result_list = self.gen_iterator() for i in result_list: print(f"call_gen_iterator-{i}") if __name__ == "__main__": obj = TestYield() obj.call_gen_iterator() 执行结果如下,可以看到一次性执行完下层函数,生成完整的迭代器类型返回值result_list,一次性返回给上层函数: 3.2 yield版本示例代码如下: class TestYield: def gen_iterator(self): for j in range(3): print(f"do_something-{j}") # yield在for循环内部 yield j def call_gen_iterator(self): # yield并不是直接返回[0,1,2],执行下边这句后result_list什么值都没有 result_list = self.gen_iterator() # i每请求一个数据,才会触发gen_iterator生成一个数据 for i in result_list: print(f"call_gen_iterator-{i}") if __name__ == "__main__": obj = TestYield() obj.call_gen_iterator() 执行结果如下,可以看到上下层函数是交替进行的,即上层函数请求迭代一个值下层函数才生成一个值并立即返回这个值: 3.3 yield的意义从上边两个小节可以看到,虽然return和yield两者执行的顺序有区别,但整个要做的事情是一样的,所以使用yield并不会比return快,甚至我们可以猜测由于yield总发生上下文切换在速度上还会慢一些,所以速度不是yield的意义。 他们的主要区别是yiled要迭代到哪个元素那个元素才即时地生成,而return要用一个中间变量result_list保存返回值,当result_list的长度很长且每个组成元素内容很大时将会耗费比较大的内存,此时yield相对return才有优势。 四、yield和return嵌套使用class TestYield: def gen_iterator(self): for j in range(3): print(f"do_something-{j}") # yield在for循环内部 yield j def gen_iterator_middle(self): print(f"gen_iterator_middle") # 返回的是迭代器的句柄,所以加一层return不影响是可以理解的 return self.gen_iterator() def call_gen_iterator(self): # yield并不是直接返回[0,1,2],执行下边这句后result_list什么值都没有 result_list = self.gen_iterator_middle() # i每请求一个数据,才会触发gen_iterator生成一个数据 for i in result_list: print(f"call_gen_iterator-{i}") if __name__ == "__main__": obj = TestYield() obj.call_gen_iterator() View Code python中的yield和return的区别return返回的是一个list列表,而yield每次调用只返回一个数值,毫无疑问,使用return空间开销比较大,尤其是操作巨量数据的时候,操作一个大列表时间开销也会得不偿失 (1)反应更迅速 (2)更节省空间 (3)使用更灵活 迭代器Iterables迭代器就是你创建一个列表,你可以一个个的读取。 lists,strings,files 等都是可以迭代的,只要你可以用for ... in ...,但是你必须把它们的值放到内存里,当它们有很多值时就会消耗太多的内存.
生成器generator生成器也是迭代器,即迭代器包括生成器,但是你只能迭代他们一次,因为他们不是全部在内存中,他们只有在调用的时候在内存中生成。
但是生成器是用()而不是用[] YieldYield的用法和关键字return差不多,下面的函数将会返回一个生成器
当for语句第一次调用函数里返回的生成器对象,函数里的代码就开始运作,直到碰到yield,然后会返回本次循环的第一个返回值.所以下一次调用也将运行一次循环然后返回下一个值,直到没有值可以返回. 一旦函数运行并没有碰到yeild语句就认为生成器已经为空了.原因有可能是循环结束或者没有满足if/else之类的. 生成器的好处
控制迭代器穷尽
迭代进阶 itertools设置起点和步长itertools.count(start=0, step=1)
itertools.cycle(iterable)
itertools.repeat(object[, times])
itertools.chain(*iterables)
itertools.groupby(iterable[, key])
itertools.permutations
更多的见 |