First of all, you are showing a common anti-pattern for Python programmers, don't loop over indices, loop over the objects themselves. E.g:
for item in b:
do_something(item)
Rather than:
for i in range(len(b)):
do_something(b[i])
It is clearer, simpler and faster.
That said, the main problem you are having is that one of the items isn't a list, so it doesn't have a length.
A better option here is to flatten the list with a generator expression and itertools.chain.from_iterable()
, and then use the sum()
builtin function to sum the elements.
>>> import collections
>>> import itertools
>>> b = [[1,2], [3,4], [5,6], 1]
>>> list(itertools.chain.from_iterable(item if isinstance(item, collections.Iterable) else [item] for item in b))
[1, 2, 3, 4, 5, 6, 1]
>>> sum(itertools.chain.from_iterable(item if isinstance(item, collections.Iterable) else [item] for item in b))
22
We need the generator expression as itertools.chain()
won't handle non-iterable items, so we place any into a list to work around this.
An alternative would be to make your own generator:
def chain_mixed(iterable):
for item in iterable:
try:
for subitem in item:
yield subitem
except TypeError:
yield item
Then you could simply do:
sum(chain_mixed(b))