Python生成器 - 不应使用的场景
我最近在研究Python的生成器,觉得它们真不错。不过,有没有什么地方不适合用生成器呢?我想到以前用C语言编程时,读取文件或者用户操作的场景。比如说,生成器能不能用来提示用户输入(比如基本的数据录入)呢?然后调用的函数再处理这些输入?在使用生成器时,有没有什么性能或者清理方面需要注意的问题呢?
3 个回答
1
当你想要让某个东西可以逐个取出来,但又不想把整个列表都放在内存里时,就可以使用生成器。这就是为什么在Python 2.x及更早版本中,xrange
可以处理比range
更长的序列。
如果你需要把整个“要生成的东西的列表”都加载到内存里,那使用生成器就没什么意义了——你直接返回一个列表就好了。
举个(稍微有点牵强的)例子:
def my_pointless_generator(x):
thedata = range(x) # or thedata = list(range(x)) in Python 3.x
for x in thedata:
yield x
..可以同样高效地改写成..
def my_pointless_generator(x):
return range(x)
13
生成器不太适合保存。
通常情况下,你尝试保存一个生成器对象时会遇到错误。
>>> def generatorForEvenKeys( aDictionary ):
for k in aDictionary:
if k % 2 == 0: yield aDictionary[k]
>>> x = generatorForEvenKeys( someDictionary )
>>> pickle.dump(x,file('temp.dat','wb'))
这会给你带来以下错误:
TypeError: can't pickle generator objects
12
生成器有一个问题,就是它们会被“消耗掉”。这意味着如果你想再次遍历这个序列,你就得重新创建这个生成器。
如果你担心懒惰求值的问题,那么你可能不想使用生成器表达式。比如说,如果你想提前完成所有计算(例如,为了释放某个资源),那么使用列表推导式或者for循环可能更合适。
如果你使用psyco,你会发现列表表达式和for循环的速度会显著提高,但生成器的速度就不会有太大变化。
还有一点很明显,如果你需要提前知道序列的长度,那么你也不应该使用生成器。