# The Built-In sum() Function

by Christoph Schiessl on Python

The built-in sum(iterable, /, start=0) function in Python has been around for a long time. It's designed to calculate the sum of a collection of numbers. Therefore, it takes one mandatory position-only parameter that must be an object implementing the iterable protocol. The second parameter, start, has a default value of 0 and is, therefore, optional.

The function sums start and the items of an iterable from left to right and returns the total. The iterable's items are typically numbers, and the start value is not allowed to be a string.

So, here is the function in action — nothing surprising:

Python 3.12.3 (main, Apr 21 2024, 14:06:33) [GCC 13.2.1 20230801] on linux
>>> sum([1, 2])
3
>>> sum([1, 2], start=3)
6
>>> sum([1.2, 2.3])
3.5
>>> sum([1.2, 2.3], start=3.1)
6.6

The parameter iterable is required but can be empty, in which case the value of start is returned.

Python 3.12.3 (main, Apr 21 2024, 14:06:33) [GCC 13.2.1 20230801] on linux
>>> sum()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sum() takes at least 1 positional argument (0 given)
>>> sum([])
0
>>> sum([], start=3)
3

Interestingly, the function has code specifically to reject str objects for the start parameter.

Python 3.12.3 (main, Apr 21 2024, 14:06:33) [GCC 13.2.1 20230801] on linux
>>> sum([], start="")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sum() can't sum strings [use ''.join(seq) instead]

However, str objects in the iterable are allowed. The error we get is indirect because start still defaults to the integer 0, and the function is then trying to calculate 0 + "A", which gives the error you see below.

Python 3.12.3 (main, Apr 21 2024, 14:06:33) [GCC 13.2.1 20230801] on linux
>>> sum(["A", "B", "C"])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
>>> 0 + "A"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'

At this point, the article becomes more theoretical, and some of the following ideas are definitely unsuitable for real-world applications. I'm pushing sum() to the limit because extreme cases are a great way to learn new concepts and solidify the ones you already know. That said, we can trick sum() into concatenating strings by providing a custom object with its own implementation of def __add__(self, other) for the start parameter. The idea is that our custom object returns the second summand as the result. So, in code, that means custom_object + whatever is whatever is always True.

Python 3.12.3 (main, Apr 21 2024, 14:06:33) [GCC 13.2.1 20230801] on linux
>>> class Trick:
...     return other
...
>>> custom_object = Trick()
>>> sum([], custom_object) is custom_object
True
>>> sum(["A"], Trick())
'A'
>>> sum(["A", "B"], Trick())
'AB'

This also demonstrates that the iterable is traversed from left to right, as the documentation states. The summation of numbers is commutative, meaning 1 + 2 == 2 + 1, but string concatenation is not: "A" + "B" != "B" + "A". The fact that the result of sum() with ["A", "B"] as the iterable is "AB", confirms the traversal happens from left to right.

Anyway, there are also legitimate use cases where you may want to use sum() with objects of custom classes. For instance, look at this example:

Python 3.12.3 (main, Apr 21 2024, 14:06:33) [GCC 13.2.1 20230801] on linux
>>> class Currency:
...   def __init__(self, value):
...     self.value = value
...     print(f"Currency({self.value}) + Currency({other.value})")
...     return Currency(self.value + other.value)
...
>>> result = sum([Currency(1), Currency(2), Currency(3)], start=Currency(4))
Currency(4) + Currency(1)
Currency(5) + Currency(2)
Currency(7) + Currency(3)
>>> print(result.value)
10

I have added the print() statement to illustrate one last point. The traversal from left to right is potentially significant in getting the correct result (if your addition is not commutative), but it's also significant if there are side effects. In this case, the text printed to stdout is a side effect that would be different if the direction of traversal of the iterable differed.

Anyway, that's everything for today. I hope you found this article interesting, and I look forward to seeing you again soon!

### Hi, I'm Christoph Schiessl.

I'm available for hire as a freelance web developer, so you can take advantage of my more than a decade of experience working on many projects across several industries. Most of my clients are building web-based SaaS applications in a B2B context and depend on my expertise in various capacities.

More often than not, my involvement includes hands-on development work using technologies like Python, JavaScript, and PostgreSQL. Furthermore, if you already have an established team, I can support you as a technical product manager with a passion for simplifying complex processes. Lastly, I'm an avid writer and educator who takes pride in breaking technical concepts down into the simplest possible terms.

#### Here are a few more Articles for you ...

The Built-In min() and max() Functions

Python's min() and max() functions can take an iterable or multiple positional parameters, and support a key parameter for custom comparisons.

By Christoph Schiessl on Python

The Built-In bin(), oct() and hex() Functions

Learn about the Python built-in functions bin(), oct(), and hex() functions for converting integers to binary, octal, and hexadecimal representations.

By Christoph Schiessl on Python