如果我要用这个内容写一个文件:
#You have been defeated!
#It's merely a flesh wound!
We are the knights who say Ni!
We are the knights who say Ni!
We are the knights who say Ni!
那么用发送器使用发生器做它会非常非pythonic吗?我从未见过其他地方使用的发电机。
def write(file, header):
with open(file,'w') as f:
f.write(header)
line = (yield)
while True:
f.write(line)
line = (yield)
return
file='holygrail.txt'
header="#You have been defeated!\n#It's merely a flesh wound!\n"
generator = write(file,header)
generator.send(None)
for i in range(3):
generator.send('We are the knights who say Ni!\n')
generator.close()
我问,因为上面的方法对我非常有益,而不是在contextlib堆栈中打开多个不同的文件流。如果我像这样编写我的文件,我根本不必使用contextlib模块。
我之前从未问过这样的问题,我不知道它是否属于stackoverflow。
我喜欢你的解决方案的创造力,但我的主观意见是使用 contextlib.ExitStack() 因为每个发电机都需要准备好,所以看起来比使用发电机更清洁,更具可读性 generator.send(None)
并明确关闭。
顺便说一句,(尽管我认为 contextlib
将导致更短,更易读的代码), write
可以简化一点:
def write(file, header):
with open(file, 'w') as f:
f.write(header)
while True:
line = (yield)
f.write(line)
return
请注意,您只需要一个 line = (yield)
而不是两个。
而且,而不是启动发电机 generator.send(None)
你可以使用 coroutine
装饰:
def coroutine(func):
""" http://www.python.org/dev/peps/pep-0342/ """
def wrapper(*args, **kw):
gen = func(*args, **kw)
gen.send(None)
return gen
return wrapper
这是一个通常被理解的习语(PEP0342, 大卫比兹利谈话)用于将发电机转变为协程。所以用它装饰你的发电机也可以用来做广告 write
是一个协程。
我认为这个问题有点主观,但我相信“Pythonic”也意味着保持简单。而对于你的特殊情况,这可能是一些事情
open("blah.txt", 'w').write("""\
#You have been defeated!
#It's merely a flesh wound!
We are the knights who say Ni!
We are the knights who say Ni!
We are the knights who say Ni!
""")
我猜你的 实际 情况虽然不同......
你的代码并不短,而且不比它更清晰
file='holygrail.txt'
header="#You have been defeated!\n#It's merely a flesh wound!\n"
with open(file, w) as fh:
fh.write(header)
for i in range(3):
fh.write('We are the knights who say Ni!\n')
所以我不确定它的好处是什么。
协程点是在.send()调用之间保存内部状态。
协同程序通常用于实现“消费者”模式(我很少使用它们来包装xlwt工作表:我需要跟踪行数以刷新它们)。没有任何状态你可以使用一个没有任何状态的简单函数(或文件对象的.write()方法)