<p>关于Python中生成器函数的预期特性的问题应该从</p>
<blockquote>
<p>implicit parallelism</p>
</blockquote>
<p>这里有一个<a href="https://en.wikipedia.org/wiki/Implicit_parallelism" rel="nofollow noreferrer">excerpt from Wikipedia</a>“在计算机科学中,隐式并行是编程语言的一个特点,它允许编译器或解释器自动利用某些语言结构所表达的计算所固有的并行性。”</p>
<p>问题的本质是,生成器函数不在两次生成之间的空闲时间内预取下一个项目,这有什么重要的原因吗?实际上是问</p>
<blockquote>
<p>"Does Python as programming language support implicit parallelism?"</p>
</blockquote>
<p>尽管事实上(问题的作者引用了作者的观点):“<em>没有任何合理的理由说明生成器函数不应该提供这种‘智能’行为。</em>“,在Python作为编程语言的上下文中,问题的实际正确答案(已经在注释中给出,但没有清楚地揭示问题的核心)是:</p>
<p><strong>Python生成器函数不应该在后台智能地预取下一项以便稍后立即交付的重要原因是Python作为编程语言
不支持隐式并行。</strong></p>
<hr/>
<p>这就是说,在这个上下文中,如果有可能以显式的方式在Python中提供预期的特性,那么在这个上下文中进行探索肯定是很有趣的?是的,这是可能的。让我们在这个上下文中演示一个生成器函数,该函数能够通过显式编程将该功能显式地预取后台的下一个项:</p>
<pre><code>from multiprocessing import Process
import time
def generatorFetchingItemsOnDemand():
for i in range(1, 4):
time.sleep(2)
print("# ...ItemsOnDemand spends 2 seconds for delivery of item")
yield i
def generatorPrefetchingItemsForImmediateDelivery():
with open('tmpFile','w') as tmpFile:
tmpFile.write('')
tmpFile.flush()
def itemPrefetcher():
for i in range(1, 4):
time.sleep(2)
print("### itemPrefetcher spends 2 seconds for prefetching an item")
with open('tmpFile','a') as tmpFile:
tmpFile.write(str(i)+'\n')
tmpFile.flush()
p = Process(target=itemPrefetcher)
p.start()
for i in range(1, 4):
with open('tmpFile','r') as tmpFile:
lstFileLines = tmpFile.readlines()
if len(lstFileLines) < i:
while len(lstFileLines) < i:
time.sleep(0.1)
with open('tmpFile','r') as tmpFile:
lstFileLines = tmpFile.readlines()
yield int(lstFileLines[i-1])
#:def
def workOnAllItems(intValue):
startTime = time.time()
time.sleep(2)
print("workOn(", intValue, "): took", (time.time()-startTime), "seconds")
return intValue
print("===============================")
genPrefetch = generatorPrefetchingItemsForImmediateDelivery()
startTime = time.time()
for item in genPrefetch:
workOnAllItems(item)
print("using genPrefetch workOnAllItems took", (time.time()-startTime), "seconds")
print(" -")
print()
print("===============================")
genOnDemand = generatorFetchingItemsOnDemand()
startTime = time.time()
for item in genOnDemand:
workOnAllItems(item)
print("using genOnDemand workOnAllItems took", (time.time()-startTime), "seconds")
print(" -")
</code></pre>
<p>提供的代码使用文件系统进行进程间通信,因此,如果您希望在自己的编程中重用此概念,用现有的其他更快的进程间通信机制来替换它,请随意使用。按照此处演示的方式实现生成器函数,执行问题作者期望的生成器函数应该做的事情,并有助于加快应用程序的速度(从12秒降到8秒):</p>
^{pr2}$