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!

Web App Reverse Checklist

Ready to Build Your Next Web App?

Get my Web App Reverse Checklist first ...


Software Engineering is often driven by fashion, but swimming with the current is rarely the best choice. In addition to knowing what to do, it's equally important to know what not to do. And this is precisely what my free Web App Reverse Checklist will help you with.

Subscribe below to get your free copy of my Reverse Checklist delivered to your inbox. Afterward, you can expect one weekly email on building resilient Web Applications using Python, JavaScript, and PostgreSQL.

By the way, it goes without saying that I'm not sharing your email address with anyone, and you're free to unsubscribe at any time. No spam. No commitments. No questions asked.

Continue Reading?

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

How to <link> your Blog's Atom/RSS Feed from HTML Pages

Learn how to <link> Atom and RSS feeds from your HTML documents to make them discoverable for clients and, by extension, for your readers.

By Christoph Schiessl

Christoph Schiessl

Hi, I'm Christoph Schiessl.

I help you build robust and fast Web Applications.


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.