Почему sum() в python предполагает, что в коллекции находятся именно числа?

Функция sum() в python3 имеет сигнатуру sum(iterable, start=0). Какая причина того, что start изначально инициализируется нулем?

Почему бы не инициализировать start внутри самой функции первым объектом коллекции, если он присутствует, а иначе возвращать None?

Зачем это может быть полезно? Для начала, просто чтобы работа функции соответствовала ожиданиям: если у меня реализован для объекта метод __add, то я хочу его складывать, и я ожидаю, что функция суммы мне сложит все мои объекты в один, а не вылетит с ошибкой TypeError.


Ответы (1 шт):

Автор решения: CrazyElf

Правильный тип возвращаемого значения, как уже упоминалось в комментарии Xander - это, на мой взгляд, основная причина такого поведения sum. Возьмём простой пример:

def my_super_sum(arr1, arr2):
    return sum(arr) * 2 - sum(arr2)

В случае, если sum точно знает, что работает с числами, проблем тут не возникнет при любой наполненности коллекций arr1 и arr2. Какие бы наборы чисел (в виде итератора) ни подать этой функции на вход, включая пустые коллекции (да, такое бывает, и это совершенно нормально) - всё будет работать, если функция sum от пустой коллекции возвращает 0. Но не в случае, если она вернёт None. Ну либо тогда придётся менять и поведение питона при сложении чисел с None, считая его нулём. Короче, всё текущее поведение питона "поплывёт".

Проблема с вашим вариантом в том, что Python - язык без строгой типизации, поэтому пустой, например, список не имеет никакого типа. Нет элементов - нет типа. Нет типа - непонятно, что мы суммируем и как.

А ещё могут быть коллекции из смешанных типов. В питоновском списке могут быть произвольные элементы, любых типов, вперемешку. Поэтому ориентироваться именно на первый элемент в данном случае как-то очень не по питоновски.

Как правильно заметил mrEvgenX, если хотите ориентироваться на первый элемент последовательности - делайте это в явном виде, используя функцию reduce, которая именно под этот вариант и заточена.

→ Ссылка