The built-in function max in Python is broken and this article explains why, drawing parallels with other programming and mathematics concepts.

`max`

is brokenDid you ever notice that in Python, you have:

```
sum([]) == 0
all([]) == True
any([]) == False
math.prod([]) == 1
```

Notice that the functions `sum`

, `all`

, `any`

, and `math.prod`

all have one thing in common:
they take a list of things and reduce it into a single result.
In all four cases above, if we pass the function an empty list we get a default value back.

However, `max`

is also a reduce function and `max`

doesn't have a nice default value.
Instead, it throws an error:

`max([]) # ValueError`

But why?
Isn't there a suitable default value for `max`

?

From a mathematical point of view, there is a suitable default value for `max`

, so the fact that the function raises an error instead of returning it is wrong and that is why I claim that `max`

is “broken”.
For `max`

to be mathematically correct, the default value for `max`

should be negative infinity, which you can get with `float("-inf")`

:

`max([]) == float("-inf")`

So, why does Python raise an error instead of being mathematically correct?
I'm guessing Python goes with the “practicality beats purity” approach and prefers to raise an error instead of returning infinity values to users, given that infinity can be quite an exotic thing...
Especially if we consider that `max`

should return *negative* infinity and `min`

should return infinity, which are different things.

(Right, I forgot to tell you but `min`

is also broken!)

But why “should” the return values be (negative) infinity?
That's because all of these reduction functions (`sum`

, `any`

, `all`

, `math.prod`

, `max`

, and `min`

) should return the identity element for their respective operations.

`sum`

performs addition and 0 is the identity element for addition.`any`

performs the Boolean operation “or” and False is the identity element for “or”.`all`

performs the Boolean operation “and” and True is the identity element for “and”.`math.prod`

performs multiplication and 1 is the identity element for multiplication.

Likewise, the identity element for the `max`

operation is `float("-inf")`

and the identity element for the `min`

operation is `float("inf")`

.

How can you know that `float("-inf")`

is the identity value for the operation `max`

?
Try to come up with a numerical value for `x`

such that `max(float("-inf"), x)`

is *different* from `x`

.
I bet you can't, and that's why `float("-inf")`

is the identity value for the operation `max`

; because `max(float("-inf"), x) == x`

for any number `x`

.

Do you get what I'm saying? Feel free to leave a comment below if you don't!

`max`

To fix `max`

in a mathematical sense you'll need to set its `default`

parameter to `float("-inf")`

.
The version below uses
`functools.partial`

to freeze the parameter `default`

:

```
from functools import partial
pedantic_max = partial(max, default=float("-inf"))
```

+35 chapters. +400 pages. Hundreds of examples. Over 30,000 readers!

My book “Pydon'ts” teaches you how to write elegant, expressive, and Pythonic code, to help you become a better developer. >>> Download it here 🐍🚀.

- “The power of
`reduce`

”, https://mathspp.com/blog/pydonts/the-power-of-reduce [last accessed 04-01-2024]; - Twitter/X post and discussion therein, https://twitter.com/mathsppblog/status/1742918859383079192 [last accessed 04-01-2024];