How to write the follwing in list comprehension in python
Question: Can I write the following in list comprehension way in python

    
    
    for row in candidates:
        sum=0
        for i in range(1,len(candidates)):
            if(row[i]!='NA')
                sum+=int(row[i])
        row.append(sum)
    

Here `candidates` is the list of list of candidates where each inner list
contains candidate marks. What I am trying to do is

"I am increasing a member in each inner list which will keep the total marks
of each candidate" like `candidate=[[143050023,5,7,6,8],[14305678,3,4,5,6]]`
(0 index in the inner has roll number of the candidate)

I want answer as

    
    
    [[143050023,5,7,6,8,26],[14305678,3,4,5,6,18]]
    

I am able to do the same without using list comprehension but facing
difficulty while trying with list comprehension The difficulty that I am
facing in writing is how to sum the value and append it to the row after each
inner loop.

When using a list comprehension is better as compared to the normal for loop
structure?


Answer: Let's start with your final question:

> When using a list comprehension is better as compared to the normal for loop
> structure?

Two things have to be true:

  * The purpose of your loop is to build a list.
  * It's more readable as a comprehension than as an explicit loop.

* * *

Notice that you have two nested loop. That _might_ be transformable into a
comprehension with two `for` clauses, or into a nested comprehension, but it's
not going to transform into a single flat comprehension.

Your inner loop has a problem: a comprehension shouldn't try to mutate
anything, and _can't_ mutate anything with an assignment or other statement.
So you need to find a way to rewrite it so that it does its work immutably.

In this case, the obvious answer is to create the values to be summed, and
then pass the resulting iterable to a function that sums them, like the
builtin `sum` function:

    
    
    sum(int(row[i]) for i in range(1, len(row)) if row[i] != 'NA')
    

I used a generator expression instead of a list comprehension because we don't
actually need the list for anything except to loop over it.

Notice that you can simplify this further. The only thing you're ever using
`i` for is in the (repeated) expression `row[i]`. So why iterate over the
range of indexes, when you can iterate over the row directly?

    
    
    sum(int(value) for value in row if value != 'NA')
    

* * *

Your outer loop has a similar problem: you're trying to mutate each `row`
inside the loop, not build up a new structure. And it's hard to come up with a
good alternative that accomplishes the same thing by building a new structure
instead.

Sure, you could always do things in two passes:

    
    
    sums = [sum(int(row[i]) for i in range(1, len(candidates)) if row[i] != 'NA')
            for row in candidates]
    candidates[:] = [row + [sum] for row, sum in zip(candidates, sums)]
    

And you can collapse those two passes into one by again changing `sums` into a
generator expression instead of a list comprehension, and you could even turn
it into a one-liner by doing it in-place instead of using a named temporary
variable:

    
    
    candidates[:] = [row + [total] for row, total in zip(candidates, (sum(
        int(row[i]) for i in range(1, len(candidates)) if row[i] != 'NA')
        for row in candidates))]
    

But it's hard to argue that's more readable, or even remotely close to as
readable, as your original version.

Also, notice that I called the variable that holds each sum `total`, not
`sum`. The `sum` function is a pretty important builtin in Python (and one
we're actually using in this answer), so hiding it by creating a variable of
the same name is a bad idea. Even in this case, where it's only alive within
the scope of a list comprehension that doesn't use the builtin, so it's not
ambiguous to the interpreter, it's still ambiguous and confusing to a human
reader. (Thanks to [Padraic
Cunningham](http://stackoverflow.com/users/2141635/padraic-cunningham) for
pointing this out.)

