Python生成器表达式和生成器(yield)用法总结
Python 中,在处理一个新序列,不想在内存中放置一个新的列表、集合或者字典。因为可能数据量比较大,不能将所有数据都放到内存中。可能只做一次遍历,而不关心是否要创建一个最终的对象容器。此时就可以使用生成器了。生成器是一种使用简洁的语法创建迭代器的工具。主要有两种方式来创建生成器:使用生成器表达式和使用带有 yield 关键字的函数。
参考文档:
1、生成器表达式
生成器表达式是一种类似于列表推导的语法,但是它返回的是一个生成器对象而不是列表。生成器表达式使用圆括号 ()
。
# 使用生成器表达式创建生成器 ret = (x ** 2 for x in range(10)) # 遍历生成器 for value in ret: print(value)
如对G量级的日志文件做处理。使用for
循环,可以一次只处理一行而不需要将下一行读入内存。并且不会创建一个最终的容器对象。则可以创建一个生成器表达式,语法很简洁。代码如下,
import sys inname = sys.argv[1] outname = sys.argv[2] with open(inname) as infile: with open(outname, "w") as outfile: warnings = (l for l in infile if 'WARNING' in l) for l in warnings: outfile.write(l)
2、生成器(yield)
yield
是生成器的关键字,可以通过编写一个普通的函数,然后在其中使用 yield
语句而不是 return
来创建生成器。当函数执行到 yield
时,它会返回一个值并暂停执行。下次从生成器中获取值时,它会从停止的地方继续执行。
# 使用 yield 创建生成器函数 def myYield(): for x in range(10): yield x ** 2 # 创建生成器 generator = myYield() # 遍历生成器 for value in generator: print(value)
可以通过yield
删除日志文件中WARNING列的例子,代码如下,
import sys iname, outname = sys.argv[1:3] def warnings_filter(p) : for l in p: if 'WARNING' in l: yield l.replace('\tWARNING',' ') with open(inname) as infile: with open(outname, "w") as outfile: filter = warnings_filter(infile) for l in filter: outfile.write(l)
带有yield
关键字函数返回的是一个生成器对象,这个对象有__iter__
和__next__
方法,每当__next__
被调用,生成器都会执行到yield
语句。然后它会返回yield
的值。当__next__
下一次被调用时,它会在上次停止的地方继续执行。
yield方法返回生成器对象
>>> help(warnings_filter([]))
Help on generator object:
warnings_filter = class generator(object)
| Methods defined here:
|
| __del__(...)
|
| __getattribute__(self, name, /)
| Return getattr(self, name).
|
| __iter__(self, /)
| Implement iter(self).
|
| __next__(self, /)
| Implement next(self).
|
| __repr__(self, /)
| Return repr(self).
|
| close(...)
| close() -> raise GeneratorExit inside generator.
|
| send(...)
| send(arg) -> send 'arg' into generator,
| return next yielded value or raise StopIteration.
|
| throw(...)
| throw(typ[,val[,tb]]) -> raise exception in generator,
| return next yielded value or raise StopIteration.
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| gi_code
|
| gi_frame
|
| gi_running
|
| gi_yieldfrom
| object being iterated by yield from, or None
通过生成器(yield
)实现,可读性可以,代码也很简洁。如果只是用for
循环或面向对象方式实现,代码应该都会稍微复杂一点。
参考文档: