digit_sum - Not sure why this is not working


This code works in a Python IDE editor but not in the exercise.

Here is the error I get:
Oops, try again. Your function fails on digit_sum(434). It returns 4 when it should return 11.

Here is my code:

def digit_sum(n):
string = str(n)
total = 0
print string

for i in string:
    total = total + int(i)
print total

x = 12345

I comments are there to help me test. When I run it I get 15 which is the correct number when x is added.

Any help would be appreciated.


I would first simplify your code a bit and delete the extraneous stuff.

Truncated Code:

def digit_sum(number):
    total = 0
    for num in str(number):
        total += int(num)
    return total

If it still does not work then you need to add some debugging to see whats going on, meaning add a print statement in your loop to print total as you calculate it.


Thanks for your quick response. Your fix does work awesome. I will check to see how you cleaned it up and see if I can see where I went wrong.


And now for something completely different...

For anyone looking for practice with list comprehensions,

def digit_sum(num):
    return sum([int(x) for x in list(str(num))])

The number is converted to a string, which is then split into a list of single character strings, then the generator converts those back to integers. The sum method computes the sum of the list members.


How about a recursive function.


# Change division symbol to proper version for floor division.
def digit_sum(number, total=0):
    return digit_sum(number // 10, total + number % 10) if number else total

I suppose I used a ternary function too but alas it does function correctly. It is basically a short complex and simple for loop. Funny how all that is in that little package.


I should mention I wrote that in python 3.* so you might have to change the division to 2.* for floor division.


Sweet! Easy to see why immersion in this concept is forestalled in this course. Until we can wrap our heads around the general algorithms, this goes right over one's head.


Two comments:
1) That's not a generator (although the for-loop does iterate through a generator that it gets from your list)
2) A string can be iterated through without first converting it to a list.

To expand on 1) a bit, at risk of saying only what you already know, but if there's a small chance I can say something new I'll take it:

A generator expression looks nearly the same as list comprehension, except the square brackets are replaced by parentheses, and these parentheses can be omitted when the generator is the only argument to a function/other callable.

List comprehension comes with an up-front cost (compute the whole list before any of it is put to use), but has less total overhead than a generator.

What a for-loop does is to request a generator from the object that is to be iterated through, something like:

>>> iterator = iter('hello')

And then it asks for next value until there's a StopIteration exception

>>> next(iterator)
>>> next(iterator)
>>> next(iterator)
>>> next(iterator)
>>> next(iterator)
>>> next(iterator)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>

So strings, lists and all other things that can be iterated through with a for-loop has an __iter__ method (that's what iter uses, similar to how len uses an objects __len__ method, they do some sanity checking as well I believe) which returns a generator.