tags:

views:

2379

answers:

4

I'm pulling a row from a db and adding up the fields (approx 15) to get a total. But some field values will be Null, which causes an error in the addition of the fields (TypeError: unsupported operand type(s) for +: 'NoneType' and 'int')

Right now, with each field, I get the field value and set it to 'x#', then check if it is None and if so set 'x#' to 0.

Not very elegant...any advice on a better way to deal with this in python?

cc

+12  A: 

You can do it easily like this:

result = sum(field for field in row if field)
Nadia Alramli
You can also use `sum(filter(None, row))`
John Millikin
Or sum(field or 0 for field in row)
dF
@John, thanks for the tip! I didn't know you could use None with filter
Nadia Alramli
'filter(None, ..)' has always seemed a bit opaque to me. You could at least do something like 'filter(bool, ..)'.
John Fouhy
A: 

Here's a clunkier version.

total = (a if a is not None else 0) + (b if b is not None else 0) + ...

Here's another choice.

def ifnull(col,replacement=0):
    return col if col is not None else replacement

total = ifnull(a) + ifnull(b) + ifnull(c) + ...

Here's another choice.

def non_null( *fields ):
    for f in fields:
        if f is not None:
            yield f

total = sum( non_null( a, b, c, d, e, f, g ) )
S.Lott
wha????? S.Lott... what's gotten into you? :-)
Jarret Hardie
They work. And they look like SQL. And that makes some programmers happy.
S.Lott
Wasn't expecting that comment reply, I must admit. Kudos.
Jarret Hardie
+1  A: 

Another (better?) option is to do this in the database. You can alter your db query to map NULL to 0 using COALESCE.

Say you have a table with integer columns named col1, col2, col3 that can accept NULLs.

Option 1:

SELECT coalesce(col1, 0) as col1, coalesce(col2, 0) as col2, coalesce(col3, 0) as col3
FROM your_table;

Then use sum() in Python on the returned row without having to worry about the presence of None.

Option 2: Sum the columns in the database and return the total in the query:

SELECT coalesce(col1, 0) + coalesce(col2, 0) + coalesce(col3, 0) as total
FROM your_table;

Nothing more to do in Python. One advantage of the second option is that you can select other columns in your query that are not part of your sum (you probably have other columns in your table and are making multiple queries to get different columns of the table?)

mhawke
+1 because my initial answer had this suggestion. Looking at how succinctly it can be done in Python, however, it's hard to argue this is better, especially if he has many fields he'd have to wrap around coalesce. Good option to know about, though. :)
Paolo Bergantino
@Paolo wrapping coalesce around every field is ugly and inflexible compared to Python, but if you had a large amount of data and/or rows, option 2 eliminates a great deal of data transfer from the db into Python. Databases are pretty fast with this stuff.
mhawke
A: 
total = 0.0
for f in fields:
  total += f or 0.0
Oli