¿Cómo funciona el aplanamiento de una lista anidada utilizando `sum (iterable, )`?

Estoy usando python 3.6. Encontré la siguiente forma de aplanar la lista anidada usando la sum :

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

que devuelve:

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

Qué está pasando aquí? La sum toma un iterable, en este caso una lista y un valor de inicio. No entiendo lo que lee Python para aplanar la lista.

Esto es solo un resultado de cómo Python interpreta la adición de listas. De los docs

sum(iterable[, start])

Las sums comienzan y los elementos de un iterable de izquierda a derecha y devuelve el total.

Dado que la sum comienza agregando el primer elemento de iterable al argumento de start , tiene:

 [] + [1, 2] = [1, 2] 

Luego continúa agregando elementos del iterable:

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

sum([a, b, c], d) produce d + a + b + c .

En su ejemplo, a , b , c y d son [1, 2] , [3, 4] , [5, 6] y [] .

sum([[1, 2], [3, 4], [5, 6]], []) produce [] + [1, 2] + [3, 4] + [5, 6] , que es [1, 2, 3, 4, 5, 6] porque + es concatenación para listas.

Esto es absurdamente ineficiente , porque cada + operación involucrada requiere copiar todos los datos de cada uno de sus argumentos:

 In [7]: x = [[i] for i in range(30000)] In [8]: %timeit sum(x, []) 1 loop, best of 3: 2.06 s per loop In [9]: %timeit [elem for sublist in x for elem in sublist] 1000 loops, best of 3: 1.91 ms per loop 

sum(x, []) toma tiempo cuadrático, mientras que una implementación más eficiente toma tiempo lineal. Nunca hagas sum(x, []) .

Como dice la sum(iterable[, start]) documento:

Las sums start y los elementos de un iterable de izquierda a derecha y devuelve el total . start predeterminado de start es 0. Los elementos del iterable normalmente son números y el valor de inicio no puede ser una cadena.

Entonces, en el ejemplo que compartiste:

 sum(a,[]) 

Aquí, iterable es a (que es [[1, 2], [3, 4], [5, 6]] ) y el start es [] . Por lo tanto, la resultante es equivalente a:

 [] + [1, 2] + [3, 4] + [5, 6] # ie you flatten list --> [1, 2, 3, 4, 5, 6] 

El argumento de start le da a la función el punto de partida. Es lo que se está agregando. Entonces, la sum([1,2,3]) devuelve 6 y la sum([1,2,3],5) devuelve 11 . En su caso, debido a que está pasando una lista 2D y una lista vacía, la función agregará todo en el primer argumento al segundo argumento. Esencialmente, estás haciendo esto:

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

Es un poco extravagante de la sobrecarga del operador de Python.