Snake Eyes
Snake Eyes

Reputation: 335

Error when declaring list in Python

Here is a small piece of Python code to add elements of a nested list:

def nested_sum(lists):
    s = [0,0,0,0,0,0,0,0]  # If I delete this line then an error is given
    for i in range(len(lists)):
        s[i] = sum(lists[i])
    print sum(s)

lists = [[1],[1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6] ]
nested_sum(lists)

Please excuse the formatting.

Issue with this code lies in the line I have commented.

The error shown was:

NameError: global name 's' is not defined

How can I avoid this error without declaring the list s before?

Upvotes: 0

Views: 400

Answers (7)

gboffi
gboffi

Reputation: 25043

You don't need any intermediate list (and no extra memory, as per the comment by Lol4t0)

def nested_sum(lists):
    print sum(sum(l) for l in lists)

the syntax I've used is a generator expression.

Of course it is much more flexible to declare your function w/o the print,

def nested_sum(lists):
    return sum(sum(l) for l in lists)

and then use it like this

l = [[1],[1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6] ]
print nested_sum(l)

Upvotes: 1

Konstanty Karagiorgis
Konstanty Karagiorgis

Reputation: 93

There is a shorter and more pythonic way of doing that:

>>> lists = [[2,4], [1]]
>>> [sum(x) for x in lists]

output: [6, 1]

You can read further on list comprehensions

Upvotes: 0

timgeb
timgeb

Reputation: 78750

If you delete the marked line you get a NameError because you try to index into something (s) before defining what that name should refer to. That should be clear.

The easiest way to solve your problem in one go is to us a generator expression in conjunction with sum with or without the chain function from itertools (depending on your preference).

Without chain:

>>> lists = [[1],[1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6] ]
>>> sum(value for sublist in lists for value in sublist)
56

With chain:

>>> from itertools import chain
>>> sum(chain(*lists))
56

which is equivalent to

>>> sum(chain.from_iterable(lists))
56

Upvotes: 3

Hassan.S
Hassan.S

Reputation: 79

Another way to do this would be to use a variable to store the sum rather than a list and use the 'in' keyword to iterate through the list items rather than a range:

def nested_sum(lists):
    list_sum = 0
    for i in lists:
        list_sum += sum(i)
    print (list_sum)

lists = [[1],[1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6] ]

nested_sum(lists)

Upvotes: 1

Idos
Idos

Reputation: 15320

Specifically in your case you don't actually need s to achieve the same functionality (if you don't mind altering the contents of lists):

def nested_sum(lists):
    for i in range(len(lists)):
        lists[i] = sum(lists[i])
    print sum(lists)

>>> lists = [[1],[1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6] ]
>>> nested_sum(lists)
56

Upvotes: 1

Mark Skelton
Mark Skelton

Reputation: 3891

You could convert your for loop to a oneliner so you don't have to pre-declare the variable s. Here is the code:

def nested_sum(lists):
    s = [sum(lists[i]) for i in range(len(lists))]  #converted for loop to oneliner
    print sum(s)

lists = [[1],[1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6] ]
nested_sum(lists)

Upvotes: 2

Sergius
Sergius

Reputation: 986

In this case, you always have to declare list. But you can choose how. For example:

1) s = [0] * len(lists) - will be equal to your declaration

2) s = [], next you do something like this:

for i in range(len(lists)):
    s.append(sum(lists[i]))

Upvotes: 1

Related Questions