"Yield None" 如何在 Python Cookbook,第 2 版中的示例中工作?
How does "Yield None" work in an example from Python Cookbook, 2nd Edition?
我正在查看 Python Cookbook, 2nd Edition(第 9.8 节)中的示例代码。
我不再能说流利的 Python -- 休息了很多年。
我对微线程很感兴趣,这是一个例子。
阅读代码时,我无法弄清 "Yield None" 的工作原理。
如果我理解的话——它会导致函数的变量被保存到堆栈上,这样函数的状态就可以在后续调用时恢复。
对于所编写的代码片段来说,这似乎太神奇了——希望得到任何帮助,谢谢。
注意:我无法将其发送到 运行
import signal
# credit: original idea was based on an article by David Mertz
# http://gnosis.cx/publish/programming/charming_python_b7.txt
# some example 'microthread' generators
def empty(name):
""" This is an empty task for demonstration purposes. """
while True:
print ("<empty process>", name)
yield None
def terminating(name, maxn):
""" This is a counting task for demonstration purposes. """
for i in xrange(maxn):
print ("Here %s, %s out of %s" % (name, i, maxn))
yield None
print ("Done with %s, bailing out after %s times" % (name, maxn))
def delay(duration=0.8):
""" Do nothing at all for 'duration' seconds. """
import time
while True:
print ("<sleep %d>" % duration)
time.sleep(duration)
yield None
class GenericScheduler(object):
def __init__(self, threads, stop_asap=False):
signal.signal(signal.SIGINT, self.shutdownHandler)
self.shutdownRequest = False
self.threads = threads
self.stop_asap = stop_asap
def shutdownHandler(self, n, frame):
""" Initiate a request to shutdown cleanly on SIGINT."""
print ("Request to shut down.")
self.shutdownRequest = True
def schedule(self):
def noop( ):
while True: yield None
n = len(self.threads)
while True:
for i, thread in enumerate(self.threads):
try: thread.next( )
except StopIteration:
if self.stop_asap: return
n -= 1
if n==0: return
self.threads[i] = noop( )
if self.shutdownRequest:
return
if __name__== "__main__":
s = GenericScheduler([ empty('boo'), delay( ), empty('foo'),
terminating('fie', 5), delay(0.5),
], stop_asap=True)
s.schedule( )
s = GenericScheduler([ empty('boo'), delay( ), empty('foo'),
terminating('fie', 5), delay(0.5),
], stop_asap=False)
s.schedule( )
老实说,我认为这段代码过于复杂,难以理解这个概念。
yield None
与 yield 1
或 yield any_other_value
没有区别
当 python 在函数代码中遇到 yield 时,它会将此函数转换为行为不同于常规函数的 special-purpose 对象。在每个 yield
上它确实 returns 值并保存当前状态。请参阅我的代码示例和一些调试信息(在 python 2.7
上测试,可能无法在 python 3.x 上运行),希望它会有所帮助
def gen():
yield 1
yield
yield 2
g = gen()
print('what is a generator')
print(type(g))
print('generator contents')
print(dir(g))
print('generator gi_frame object')
print(dir(g.gi_frame))
print('code line')
print(g.gi_frame.f_lineno)
print('step 1')
print(next(g))
print('generator state after step 1')
print(g.gi_frame.f_lineno)
print('step 2')
print(next(g))
print('generate state after step 2');
print(g.gi_frame.f_lineno)
print('last step')
print(next(g))
print(g.gi_frame.f_lineno)
print('nothing left')
try:
print(next(g))
except StopIteration as e:
print('got StopIteration')
print(g.gi_frame)
输出:
what is a generator
<type 'generator'>
generator contents
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'next', 'send', 'throw']
generator gi_frame object
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'f_back', 'f_builtins', 'f_code', 'f_exc_traceback', 'f_exc_type', 'f_exc_value', 'f_globals', 'f_lasti', 'f_lineno', 'f_locals', 'f_restricted', 'f_trace']
code line
1
step 1
1
generator state after step 1
2
step 2
None
generate state after step 2
3
last step
2
4
nothing left
got StopIteration
None
我正在查看 Python Cookbook, 2nd Edition(第 9.8 节)中的示例代码。
我不再能说流利的 Python -- 休息了很多年。
我对微线程很感兴趣,这是一个例子。
阅读代码时,我无法弄清 "Yield None" 的工作原理。
如果我理解的话——它会导致函数的变量被保存到堆栈上,这样函数的状态就可以在后续调用时恢复。
对于所编写的代码片段来说,这似乎太神奇了——希望得到任何帮助,谢谢。
注意:我无法将其发送到 运行
import signal
# credit: original idea was based on an article by David Mertz
# http://gnosis.cx/publish/programming/charming_python_b7.txt
# some example 'microthread' generators
def empty(name):
""" This is an empty task for demonstration purposes. """
while True:
print ("<empty process>", name)
yield None
def terminating(name, maxn):
""" This is a counting task for demonstration purposes. """
for i in xrange(maxn):
print ("Here %s, %s out of %s" % (name, i, maxn))
yield None
print ("Done with %s, bailing out after %s times" % (name, maxn))
def delay(duration=0.8):
""" Do nothing at all for 'duration' seconds. """
import time
while True:
print ("<sleep %d>" % duration)
time.sleep(duration)
yield None
class GenericScheduler(object):
def __init__(self, threads, stop_asap=False):
signal.signal(signal.SIGINT, self.shutdownHandler)
self.shutdownRequest = False
self.threads = threads
self.stop_asap = stop_asap
def shutdownHandler(self, n, frame):
""" Initiate a request to shutdown cleanly on SIGINT."""
print ("Request to shut down.")
self.shutdownRequest = True
def schedule(self):
def noop( ):
while True: yield None
n = len(self.threads)
while True:
for i, thread in enumerate(self.threads):
try: thread.next( )
except StopIteration:
if self.stop_asap: return
n -= 1
if n==0: return
self.threads[i] = noop( )
if self.shutdownRequest:
return
if __name__== "__main__":
s = GenericScheduler([ empty('boo'), delay( ), empty('foo'),
terminating('fie', 5), delay(0.5),
], stop_asap=True)
s.schedule( )
s = GenericScheduler([ empty('boo'), delay( ), empty('foo'),
terminating('fie', 5), delay(0.5),
], stop_asap=False)
s.schedule( )
老实说,我认为这段代码过于复杂,难以理解这个概念。
yield None
与 yield 1
或 yield any_other_value
当 python 在函数代码中遇到 yield 时,它会将此函数转换为行为不同于常规函数的 special-purpose 对象。在每个 yield
上它确实 returns 值并保存当前状态。请参阅我的代码示例和一些调试信息(在 python 2.7
上测试,可能无法在 python 3.x 上运行),希望它会有所帮助
def gen():
yield 1
yield
yield 2
g = gen()
print('what is a generator')
print(type(g))
print('generator contents')
print(dir(g))
print('generator gi_frame object')
print(dir(g.gi_frame))
print('code line')
print(g.gi_frame.f_lineno)
print('step 1')
print(next(g))
print('generator state after step 1')
print(g.gi_frame.f_lineno)
print('step 2')
print(next(g))
print('generate state after step 2');
print(g.gi_frame.f_lineno)
print('last step')
print(next(g))
print(g.gi_frame.f_lineno)
print('nothing left')
try:
print(next(g))
except StopIteration as e:
print('got StopIteration')
print(g.gi_frame)
输出:
what is a generator
<type 'generator'>
generator contents
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'next', 'send', 'throw']
generator gi_frame object
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'f_back', 'f_builtins', 'f_code', 'f_exc_traceback', 'f_exc_type', 'f_exc_value', 'f_globals', 'f_lasti', 'f_lineno', 'f_locals', 'f_restricted', 'f_trace']
code line
1
step 1
1
generator state after step 1
2
step 2
None
generate state after step 2
3
last step
2
4
nothing left
got StopIteration
None