Note that there are some explanatory texts on larger screens.

plurals
  1. POavoiding code duplication in Python code
    primarykey
    data
    text
    <p>Consider the following Python snippet:</p> <pre><code>af=open("a",'r') bf=open("b", 'w') for i, line in enumerate(af): if i &lt; K: bf.write(line) </code></pre> <p>Now, suppose I want to handle the case where <code>K</code> is <code>None</code>, so the writing continues to the end of the file. I'm currently doing </p> <pre><code>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 </code></pre> <p>This clearly isn't the best way to handle this, as I'm duplicating the code. Is there some more integrated way I can handle this? The natural thing would be to have the <code>if/break</code> code only be present if <code>K</code> is not <code>None</code>, but this involves writing syntax on the fly a la Lisp macros, which Python can't really do. Just to be clear, I'm not concerned about the particular case (which I choose partly for its simplicity), so much as learning about general techniques I may not be familar with.</p> <p>UPDATE: After reading answers people have posted, and doing more experimentation, here are some more comments.</p> <p>As said above, I was looking for general techniques that would be generalizable, and I think @Paul's answer,namely using <code>takewhile</code> from <code>iterrools</code>, fits that best. As a bonus, it is also much faster than the naive method i listed above; I'm not sure why. I'm not really familar with <code>itertools</code>, though I've looked at it a few times. From my perspective this is a case of functional programming <em>For The Win</em>! (Amusingly, the author of <code>itertools</code> once asked for feedback about dropping <code>takewhile</code>. See the thread beginning <a href="http://mail.python.org/pipermail/python-list/2007-December/522529.html" rel="nofollow">http://mail.python.org/pipermail/python-list/2007-December/522529.html</a>.) I'd simplified my situation above, the actual situation is a bit more messy - I'm writing to two different files in the loop. So the code looks more like:</p> <pre><code>for i, line in enumerate(af): if i &lt; K: bf.write(line) cf.write(line.split(',')[0].strip('"')+'\n') </code></pre> <p>Given my posted example, @Jeff reasonably suggested that in the case when <code>K</code> was <code>None</code>, I just copy the file. Since in practice I am looping anyway, doing so is not such a clear choice. However, <code>takewhile</code> generalizes painlessly to this case. I also had another use case I did not mention here, and was able to use <code>takewhile</code> there too, which was nice. The second example looks like (verbatim)</p> <pre><code>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) </code></pre> <p>here I was able to use the condition</p> <pre><code>if K is None: illuminacond = lambda x: x.split(',')[0] != '[Controls]' else: illuminacond = lambda x: x.split(',')[0] != '[Controls]' and i &lt; K </code></pre> <p>per @Paul's original example. However, I'm not completely happy about the fact that I'm getting <code>i</code> from the outer scope, though the code works. Is there a better way of doing this? Or maybe it should be a separate question. Anyway, thanks to everyone who answered my question. Honorable mention to @Jeff, who made some nice suggestions.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload