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
Type "help", "copyright", "credits" or "license" for more information.
>>> 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
Type "help", "copyright", "credits" or "license" for more information.
>>> 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
Type "help", "copyright", "credits" or "license" for more information.
>>> 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
Type "help", "copyright", "credits" or "license" for more information.
>>> 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
Type "help", "copyright", "credits" or "license" for more information.
>>> class Trick:
...   def __add__(self, other):
...     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
Type "help", "copyright", "credits" or "license" for more information.
>>> class Currency:
...   def __init__(self, value):
...     self.value = value
...   def __add__(self, other):
...     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!

Ready to Learn More Web Development?

Join my Mailing List to receive 1-2 useful Articles per week.


I send two weekly emails on building performant and resilient Web Applications with Python, JavaScript and PostgreSQL. No spam. Unscubscribe at any time.

Continue Reading?

Here are a few more Articles for you ...


The Built-in all() Function

Learn how to use the built-in all() function in Python for boolean logic, with examples and different implementations.

By Christoph Schiessl on Python

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

How to Find the First/Last Day of a Month from a given Date

Learn how to calculate a month's first and last days using Python's built-in datetime module, with step-by-step explanations and code examples.

By Christoph Schiessl on Python

Christoph Schiessl

Christoph Schiessl

Independent Consultant + Full Stack Developer


If you hire me, you can rely on more than a decade of experience, which I have collected working on web applications for many clients across multiple industries. My involvement usually focuses on hands-on development work using various technologies like Python, JavaScript, PostgreSQL, or whichever technology we determine to be the best tool for the job. Furthermore, you can also depend on me in an advisory capacity to make educated technological choices for your backend and frontend teams. Lastly, I can help you transition to or improve your agile development processes.