如果我要用这个内容写一个文件:
#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!
使用send使用生成器执行此操作会非常非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。
答案 0 :(得分:10)
我喜欢你的解决方案的创造力,但我的主观意见是使用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,David Beazley talk),用于将生成器转换为协程。因此,用它来装饰你的发电机也可以用来宣传write
是一个协程。
答案 1 :(得分:0)
我认为这个问题有些主观,但我相信“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!
""")
我猜你的实际情况虽然不同......
答案 2 :(得分:0)
你的代码并不比
更短,也没有更清晰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')
所以我不确定它的好处是什么。
答案 3 :(得分:0)
协程的意义在于.send()调用之间保存内部状态。
协程通常用于实现"消费者"模式(我很少使用它们来包装xlwt工作表:我需要跟踪要刷新它们的行数)。没有任何状态,你可以使用一个没有任何状态的简单函数(或文件对象的.write()方法)