【发布时间】:2011-05-02 22:45:15
【问题描述】:
考虑以下 Python sn-p:
af=open("a",'r')
bf=open("b", 'w')
for i, line in enumerate(af):
if i < K:
bf.write(line)
现在,假设我要处理K 是None 的情况,
所以写入继续到文件的末尾。
我现在在做
if K is None:
for i, line in enumerate(af):
bf.write(line)
else:
for i, line in enumerate(af):
bf.write(line)
if i==K:
break
这显然不是处理此问题的最佳方法,因为我正在复制代码。
有没有更综合的方法可以处理这个问题?自然的事情是
仅当K 不是None 时才存在if/break 代码,
但这涉及像 Lisp 宏那样动态编写语法,
Python 真的做不到。为了清楚起见,我不关心特定的
案例(我选择它的部分原因是为了它的简单性),就像学习一般知识一样
我可能不熟悉的技术。
更新:阅读人们发布的答案并进行更多实验后,这里还有一些 cmets。
如上所述,我一直在寻找可以推广的通用技术,我认为@Paul 的答案,即使用来自iterrools 的takewhile 最适合。作为奖励,它也比我上面列出的简单方法快得多;我不确定为什么。我对itertools 不是很熟悉,虽然我看过几次。从我的角度来看,这是一个函数式编程的案例For The Win! (有趣的是,itertools 的作者曾经询问有关删除takewhile 的反馈。请参阅以http://mail.python.org/pipermail/python-list/2007-December/522529.html 开头的线程。)我在上面简化了我的情况,实际情况有点混乱 - 我正在写信给循环中的两个不同文件。所以代码看起来更像:
for i, line in enumerate(af):
if i < K:
bf.write(line)
cf.write(line.split(',')[0].strip('"')+'\n')
鉴于我发布的示例,@Jeff 合理地建议在 K 为 None 的情况下,我只需复制文件。因为在实践中我无论如何都在循环,这样做并不是一个明确的选择。然而,takewhile 轻松地概括了这种情况。我还有另一个在这里没有提到的用例,并且也可以在那里使用takewhile,这很好。第二个例子看起来像(逐字)
i=0
for line in takewhile(illuminacond, af):
line_split=line.split(',')
pid=line_split[1][0:3]
out = line_split[1] + ',' + line_split[2] + ',' + line_split[3][1] + line_split[3][3] + ',' \
+ line_split[15] + ',' + line_split[9] + ',' + line_split[10]
if pid!='cnv' and pid!='hCV' and pid!='cnv':
i = i+1
of.write(out.strip('"')+'\n')
tf.write(line)
在这里我可以使用条件
if K is None:
illuminacond = lambda x: x.split(',')[0] != '[Controls]'
else:
illuminacond = lambda x: x.split(',')[0] != '[Controls]' and i < K
根据@Paul 的原始示例。但是,尽管代码有效,但我对从外部范围获得i 这一事实并不完全满意。有没有更好的方法来做到这一点?或者也许它应该是一个单独的问题。无论如何,感谢所有回答我问题的人。向@Jeff 表扬,他提出了一些很好的建议。
【问题讨论】:
-
只是一个小评论:对于与 None 的比较
isis prefered over using==.
标签: python code-duplication control-flow