Что делает сумма встроенной функции суммой (list, [])?

Когда я хочу развернуть список, я нашел способ, как показано ниже:

>>> a = [[1, 2], [3, 4], [5, 6]]
>>> a
[[1, 2], [3, 4], [5, 6]]
>>> sum(a, [])
[1, 2, 3, 4, 5, 6]

Я не знаю, что произошло в этих строках, и в документации говорится:

sum(iterable[, start])

Суммы start и элементы iterable слева направо и возвращают iterable. start умолчанию 0. Итерируемые элементы обычно являются числами, и start значение не может быть строкой.

Для некоторых случаев использования есть хорошие альтернативы sum(). Предпочтительный быстрый способ объединения последовательности строк - это вызов ''.join(sequence). Чтобы добавить значения с плавающей запятой с расширенной точностью, см. math.fsum(). Чтобы объединить серию итераций, рассмотрите использование itertools.chain().

Новое в версии 2.3.

Тебе не кажется, что начало должно быть числом? Почему [] можно написать здесь?

(sum(a, []))

Ответы

Ответ 1

Вам не кажется, что начало должно быть числом?

start - это число, по умолчанию; 0, в документации, которую вы указали. Следовательно, когда вы делаете, например:

sum((1, 2))

он оценивается как 0 + 1 + 2, и он равен 3, и все счастливы. Если вы хотите начать с другого номера, вы можете указать это вместо:

>>> sum((1, 2), 3)
6

До сих пор так хорошо.


Однако есть и другие вещи, которые вы можете использовать +, например, списки:

>>> ['foo'] + ['bar']
['foo', 'bar']

Если вы попытаетесь использовать sum для этого, однако, ожидая того же результата, вы получите TypeError:

>>> sum((['foo'], ['bar']))

Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    sum((['foo'], ['bar']))
TypeError: unsupported operand type(s) for +: 'int' and 'list'

потому что теперь он выполняет 0 + ['foo'] + ['bar'].

Чтобы исправить это, вы можете указать свой собственный start как [], поэтому он становится [] + ['foo'] + ['bar'], и все снова хорошо. Поэтому, чтобы ответить:

Почему [] можно записать здесь?

потому что хотя start по умолчанию используется число, оно не обязательно должно быть одним; другие вещи также могут быть добавлены, и это пригодится для вещей точно так же, как то, что вы сейчас делаете.

Ответ 2

Функция sum вызывает атрибут __add__ start каждой итерации со всеми элементами итерируемого, которые были переданы в качестве первого аргумента.

Например:

>>> [].__add__([2,3])
[2, 3]
#OR
>>> [] + [1,2,3]
[1, 2, 3]

И в этом случае результатом будет составной список ваших входных списков. С алгоритмической точки зрения это делает следующее:

>>> a = [[1, 2], [3, 4], [5, 6]]
>>> start = []
>>> for i in a:
...     start += i
... 
>>> start
[1, 2, 3, 4, 5, 6]

Не то чтобы вы могли вызывать функцию sum для любой последовательности объектов, имеющих атрибут __add__, но учтите, что, поскольку аргумент start по умолчанию равен 0 если ваш объект не является целым числом, он вызовет TypeError. В этом случае вам нужно указать правильное start для функции.

>>> class newObj(object):
...    def  __init__(self,val):
...         self.val = val
...    def __add__(self,item):
...        return '{}_____{}'.format(self.val,item)
... 
>>> 
>>> start=newObj('new_obj')
>>> 
>>> start
<__main__.newObj object at 0x7f75f9241c50>
>>> 
>>> start + 5
'new_obj_____5'
>>> 
>>> 
>>> sum(['1','2','3'],start)
'new_obj_____123'

Ответ 3

Вы суммируете start с содержимым итерабельного, которое вы предоставляете в качестве первого аргумента. sum не ограничивает type of start значением int, чтобы допускать различные случаи добавления.

Существенно сумма делает что-то вроде этого:

a = [[1, 2], [3, 4], [5, 6]]
sum(a, number)

Грубо переводит на:

number += every value in the list a

Так как каждое значение в списке a является списком, это работает, и предыдущее суммирование при расширении выглядит следующим образом:

number + [1, 2] + [3, 4] + [5, 6]

Итак, если вы введете int, это приведет к неудачной TypeError, потому что добавление int и a list недопустимо.

1 + [1, 2] == I hope you like TypeErrors

Однако, если вы введете список [], он просто объединит элементы a вместе и приведет к сглаженному списку, который мы знаем и любим.

Значение start по умолчанию равно 0 a int главным образом потому, что наиболее распространенный случай суммирования является арифметическим.