Что делает сумма встроенной функции суммой (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
главным образом потому, что наиболее распространенный случай суммирования является арифметическим.