¿Es posible acceder al objeto actual mientras se hace la comprensión de lista / dictado en Python?

Intentando pensar en una sola línea para lograr lo siguiente (sumndo todos los valores de una clave):

>>> data = [('a',1),('b',3),('a',4),('c',9),('b',1),('d',3)] >>> res = {} >>> for tup in data: ... res[tup[0]] = res.setdefault(tup[0],0) + tup[1] ... >>> res {'a': 5, 'c': 9, 'b': 4, 'd': 3} 

Versión de una sola línea sin utilizar ninguna importación como itertools, colecciones, etc.

  { tup[0] : SELF_REFERENCE.setdefault(tup[0],0) + tup[1] for tup in data } 

¿Es posible en Python usar una referencia al objeto que se está comprendiendo actualmente? Si no es así, ¿hay alguna forma de lograr esto en una sola línea sin usar ninguna importación? Es decir, utilizando la comprensión básica de lista / dict y las funciones incorporadas.

No no hay. Una comprensión de dict produce un nuevo elemento para cada iteración, y su código debe producir menos elementos (valores de consolidación).

No hay manera de acceder a las claves producidas en una iteración anterior, no sin utilizar trucos de efectos secundarios (feos, no pirónicos). El objeto de dict que se va a producir por la comprensión no existe todavía, por lo que tampoco hay manera de producir una auto-referencia.

Solo apégate a tu bucle for , es mucho más legible.

La alternativa sería utilizar la clasificación y agrupación, un algoritmo O (NlogN) frente a la simple O (N) de su bucle directo:

 from itertools import groupby from operator import itemgetter res = {key: sum(t[1] for t in group) for key, group in groupby(sorted(data, key=itemgetter(0)), key=itemgetter(0))} 

No uses un oneliner. En su lugar, utilice collections.defaultdict y un simple for loop:

 >>> pairs = [('a', 1), ('b', 3), ('a', 4), ('c', 9), ('b', 1), ('d', 3)] >>> result = defaultdict(int) >>> for key, value in pairs: ... result[key] += value ... >>> result defaultdict(, {'a': 5, 'c': 9, 'b': 4, 'd': 3}) 

Es fácil de entender, pythonico y rápido.

Uso reduce y collections.Counter . collections.Counter :

 >>> from operator import add >>> from collections import Counter >>> reduce(add, (Counter(dict([x])) for x in data)) Counter({'c': 9, 'a': 5, 'b': 4, 'd': 3}) 

Esto es casi como, lo que estás tratando de hacer. Pero no lo recomendaré, ya que la legibilidad sufre.

 data = [('a',1),('b',3),('a',4),('c',9),('b',1),('d',3)] print reduce(lambda d,i: [d.__setitem__(i[0],d.get(i[0],0)+i[1]),d][1], data, {}) 

Salida

 {'a': 5, 'c': 9, 'b': 4, 'd': 3}