2011-04-23 11 views
6

¿Hay alguna forma de utilizar métodos sin valor de retorno como random.shuffle en una lista de comprensión?Aplicar un método sin valor de retorno a cada elemento de una lista

>>> import pprint 
>>> import random 
>>> 
>>> L = [ random.shuffle(range(5)) for x in range(5)] 
>>> 
>>> print L 
[None, None, None, None, None] 

Este es el bucle que se aplica el método random.shuffle a cada elemento de la lista:

>>> L = [ range(5) for x in range(5) ] 
>>> pprint.pprint(L) 
[[0, 1, 2, 3, 4], 
[0, 1, 2, 3, 4], 
[0, 1, 2, 3, 4], 
[0, 1, 2, 3, 4], 
[0, 1, 2, 3, 4]] 
>>> for element in L: 
...  random.shuffle(element) 
... 
>>> pprint.pprint(L) 
[[2, 0, 3, 1, 4], 
[2, 0, 1, 4, 3], 
[4, 1, 3, 0, 2], 
[1, 2, 4, 3, 0], 
[1, 3, 0, 2, 4]] 

puedo usar un mapa, que como efecto secundario baraja la lista original, sino que devuelve una lista de None

>>> L = [ range(5) for x in range(5) ] 
>>> pprint.pprint(L) 
[[0, 1, 2, 3, 4], 
[0, 1, 2, 3, 4], 
[0, 1, 2, 3, 4], 
[0, 1, 2, 3, 4], 
[0, 1, 2, 3, 4]] 
>>> map(random.shuffle, L) 
[None, None, None, None, None] 
>>> pprint.pprint(L) 
[[3, 0, 4, 1, 2], 
[2, 3, 0, 1, 4], 
[2, 3, 1, 4, 0], 
[4, 2, 0, 3, 1], 
[1, 3, 0, 2, 4]] 

al igual que el uso de la lista por comprensión con la reproducción aleatoria:

>>> L = [ range(5) for x in range(5) ] 
>>> pprint.pprint(L) 
[[0, 1, 2, 3, 4], 
[0, 1, 2, 3, 4], 
[0, 1, 2, 3, 4], 
[0, 1, 2, 3, 4], 
[0, 1, 2, 3, 4]] 
>>> L1 = [ random.shuffle(x) for x in L ] 
>>> pprint.pprint(L1) 
[None, None, None, None, None] 
>>> pprint.pprint(L) 
[[1, 4, 0, 2, 3], 
[0, 4, 1, 3, 2], 
[2, 3, 4, 0, 1], 
[4, 1, 0, 2, 3], 
[2, 0, 4, 3, 1]] 

Muchas preguntas y respuestas sobre el desbordamiento de pila ya señalan que el uso de map o un lc para el efecto secundario es una mala práctica. Me preguntaba si hay alguna forma correcta de usar un método sin valor de retorno en una lista de comprensión.

está escribiendo un método para envolver el método no devolver la única manera:

>>> def shuffled(L): 
...  ret_val = L[:] 
...  random.shuffle(ret_val) 
...  return ret_val 
... 
>>> L = [ shuffled(range(5)) for x in range(5)] 
>>> pprint.pprint(L) 
[[2, 1, 0, 4, 3], 
[4, 0, 3, 1, 2], 
[4, 2, 3, 0, 1], 
[1, 0, 4, 2, 3], 
[2, 4, 3, 0, 1]] 
>>> 
+0

me gusta su método 'shuffled', vaya con la de una lista de comprensión! – sjr

+0

Relacionados: http: // stackoverflow.com/questions/5753597/is-it-pythonic-to-use-list-comprehensions-for-just-side-effects – delnan

Respuesta

8

n - listas por comprensión están destinados a ser su uso con funciones que tienen valores de retorno. Es la forma de su semántica are defined:

Las listas por comprensión proporcionan una manera concisa para crear listas sin tener que recurrir al uso de del mapa(), filter() y/o lambda. La definición de lista resultante tiende a ser más clara que las listas construidas usando esas construcciones. Cada lista de comprensión de consiste en una expresión seguida de una cláusula for, y luego cero o más para las cláusulas if. El resultado será una lista resultante de evaluar la expresión en el contexto de las cláusulas if y if que lo siguen.

Al leer esto, debe quedar claro que "una comprensión de la lista de una función que no tiene valor de retorno" es un oxímoron.

sólo tiene que utilizar un bucle for por algo "excepcional":

import random 
L = [] 
for x in range(5): 
    l = range(5) 
    random.shuffle(l) 
    L.append(l) 

limpio y sencillo. Su función shuffled también está bien, y puede utilizarse en una lista de comprensión.

4

Eli tiene toda la razón. Pero me gustaría ir por algo más concisa:

import random 

L = [range(5) for each in xrange(5)] 
for each in L: 
    random.shuffle(each) 

[editar]

otoh podría utilizar random.sample():

from random import sample 

xr = xrange(5) 
L = [sample(xr, 5) for each in xr] 
+0

+1 Gracias por la respuesta y por señalar la muestra. – DTing

Cuestiones relacionadas