简体   繁体   中英

can someone explain how this python code doesn't give an error

So I have inherited a rather crappy piece of code. Indentation is as I found it. Why does the else not throw an error? The code will never reach it as far as I understand.

    for l in range(1,9):
        indexes = pickle.load(open('%s_%d.pkl'%(fc,l)))

        clusters_sum = sum([indexes[i]['count'] for i in indexes])
        print >> out, 'Lane %d: %d clusters PF.\n%8s  %9s  %5s' % (l,clusters_sum,'Index','Count','%')
        for i in sorted(indexes, key=lambda x: indexes[x]['name']):
            pct = indexes[i]['count'] and indexes[i]['count']/clusters_sum*100 or 0
            if pct < 0.06: continue
            print >> out, '%8s  %9d  %5.1f' % (indexes[i]['name'], indexes[i]['count'], pct)
        else: print >> out

See the documentation on else clauses on loops , this is valid syntax and the code within the else block is executed as long as there was no break , return , or uncaught exception within the loop.

In this particular case the else clause will always be executed since none of the above conditions (other than an exception) can happen, so it is equivalent to the following:

    for l in range(1,9):
        indexes = pickle.load(open('%s_%d.pkl'%(fc,l)))

        clusters_sum = sum([indexes[i]['count'] for i in indexes])
        print >> out, 'Lane %d: %d clusters PF.\n%8s  %9s  %5s' % (l,clusters_sum,'Index','Count','%')
        for i in sorted(indexes, key=lambda x: indexes[x]['name']):
            pct = indexes[i]['count'] and indexes[i]['count']/clusters_sum*100 or 0
            if pct < 0.06: continue
            print >> out, '%8s  %9d  %5.1f' % (indexes[i]['name'], indexes[i]['count'], pct)
        
        print >> out

for loops can have an else clause.

From http://docs.python.org/tutorial/controlflow.html#break-and-continue-statements-and-else-clauses-on-loops :

Loop statements may have an else clause; it is executed when the loop terminates through exhaustion of the list (with for) or when the condition becomes false (with while), but not when the loop is terminated by a break statement.

Since the loop doesn't contain a break statement, the else clause will always be executed.

Not sure if you're not understanding the indentation (or lack thereof) on the else statement, or the fact that there is an "else" on the for loop. If the former case...

The formatting is valid because print >> out is a "simple statement".

Here is the grammar for a for statement :

for_stmt ::=  "for" target_list "in" expression_list ":" suite
              ["else" ":" suite]

Notice that after the colon in the optional "else" block, it wants a " suite ", the grammar of which is...

suite         ::=  stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT
statement     ::=  stmt_list NEWLINE | compound_stmt
stmt_list     ::=  simple_stmt (";" simple_stmt)* [";"]

So, it's possible in python to create a list of simple statements as an alternative to a block of statements. This is also valid...

for i in sorted(indexes, key=lambda x: indexes[x]['name']):
    pct = indexes[i]['count'] and indexes[i]['count']/clusters_sum*100 or 0
    if pct < 0.06: continue
    print >> out, '%8s  %9d  %5.1f' % (indexes[i]['name'], indexes[i]['count'], pct)
else: print >> out; print >> out; print >> out

and would be equivalent to...

for i in sorted(indexes, key=lambda x: indexes[x]['name']):
    pct = indexes[i]['count'] and indexes[i]['count']/clusters_sum*100 or 0
    if pct < 0.06: continue
    print >> out, '%8s  %9d  %5.1f' % (indexes[i]['name'], indexes[i]['count'], pct)
else:
    print >> out
    print >> out
    print >> out

However, I think most people would prefer seeing the second syntax.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM