我试图理解函数和生成器之间的区别,并为此目的使用了下面的代码。但是,我不理解输出。
class GeneratorsSample(object):
def DoReturn(self):
counter, maxCounter = 0, 5
listResults = []
while counter < maxCounter:
print "tic"
listResults.append(counter*2)
counter += 1
return listResults
def DoYield(self):
counter, maxCounter = 0, 5
listResults = []
while counter < maxCounter:
print "tic"
listResults.append(counter*2)
yield listResults #to return the entire list
#yield listResults[counter] #you can only return one item at a time
counter += 1
return
generatorSample = GeneratorsSample()
我不明白为什么,DoReturn()
的输出与DoYield()
的输出不同。例如,
returnResults = generatorSample.DoReturn()
for r in returnResults:
print "toc", r
输出:
tic
tic
tic
tic
tic
toc 0
toc 2
toc 4
toc 6
toc 8
而且,
yieldResults = generatorSample.DoYield()
for r in yieldResults:
print "toc", r
输出:
tic
toc [0]
tic
toc [0, 2]
tic
toc [0, 2, 4]
tic
toc [0, 2, 4, 6]
tic
toc [0, 2, 4, 6, 8]
答案 0 :(得分:2)
这可能是一个更好的例子:
class GeneratorsSample(object):
def DoReturn(self):
counter, maxCounter = 0, 5
listResults = []
while counter < maxCounter:
print "tic"
listResults.append(counter*2)
counter += 1
return listResults
def DoYield(self):
counter, maxCounter = 0, 5
while counter < maxCounter:
print "tic"
yield counter*2
counter += 1
return
generatorSample = GeneratorsSample()
ret = generatorSample.DoReturn()
yld = generatorSample.DoYield()
for r in ret: print "toc", r
for r in yld: print "toc", r
print ret
print yld
首先看看以下几行:
for r in ret: print "toc", r
for r in yld: print "toc", r
生成相同的值,但在&#34; return&#34;版本,抽搐都是第一个,然后是所有的tocs。在&#34;产量&#34;版本tics和tocs是穿插的。
但这两种方法之间的关键区别如下:
print ret # prints: [0, 2, 4, 6, 8]
print yld # prints: <generator object DoYield at 0x0000000002202630>
此处,ret
是生成的所有值的列表。也就是说,在进行此分配时:
ret = generatorSample.DoReturn()
整个列表生成然后,并作为完整列表返回。
使用生成器方法,生成整个列表 ,实际上,没有计算任何元素。只是对生成器的引用,它将生成元素&#34;只需要飞行&#34;,根据需要。
换句话说,&#34;返回&#34;的方法:
generates a number generates a number generates a number ... uses that number uses that number uses that number ...
而发电机方法:
generates a number uses that number generates a number uses that number ...
生成器的效率在于它们只需要花时间生成单个元素,因为它们是需要的(如果它们是需要的话)。如果maxCounter
是100万,并且计算比counter * 2
更复杂,那么您获得第一个输出所需的时间会有明显的改善。
事实上,您可以通过添加人工延迟(此处为time.sleep(1)
:
import time
class GeneratorsSample(object):
def DoReturn(self):
counter, maxCounter = 0, 5
listResults = []
while counter < maxCounter:
v = counter * 2
time.sleep(1)
print "[DoReturn] computed %d" % v
listResults.append(v)
counter += 1
return listResults
def DoYield(self):
counter, maxCounter = 0, 5
while counter < maxCounter:
v = counter * 2
time.sleep(1)
print "[DoYield] computed %d" % v
yield counter*2
counter += 1
return
generatorSample = GeneratorsSample()
ret = generatorSample.DoReturn()
yld = generatorSample.DoYield()
for r in ret: print "[return loop] using", r
print("")
for r in yld: print "[yield loop] using", r
输出为:
[DoReturn] computed 0 [DoReturn] computed 2 [DoReturn] computed 4 [DoReturn] computed 6 [DoReturn] computed 8 [return loop] using 0 [return loop] using 2 [return loop] using 4 [return loop] using 6 [return loop] using 8 [DoYield] computed 0 [yield loop] using 0 [DoYield] computed 2 [yield loop] using 2 [DoYield] computed 4 [yield loop] using 4 [DoYield] computed 6 [yield loop] using 6 [DoYield] computed 8 [yield loop] using 8