2012-05-11 28 views
10

Quiero aplicar una función a todos los elementos en la lista, pero realmente quiero cambiar los elementos (que son objetos), no ver los resultados. Creo que este es el problema con el uso de map() o listas de comprensión.¿Cómo aplicar la función a los elementos de una lista?

class Thing(object): 
    pass 

# some collection of things 
my_things 

# they are all big... 

# produces SyntaxError: invalid syntax 
[i.size = "big" for i in my_things] 

# produces SyntaxError: lambda cannot contain assignment 
map(lambda i: i.size="big", [i for i in my_things]) 

# no error, but is it the preferred way? 
for i in my_things: 
    i.size="big" 

¿Cuál es la manera de hacer esto?

Respuesta

13

Y lo que es malo en

for i in my_things: 
    i.size = "big" 

Usted no desea utilizar ni map ni lista comprehansion porque en realidad crean nuevas listas. Y no necesitas esa sobrecarga, ¿verdad?

+0

No sabía que ese mapa hizo una nueva lista, que está criando algunas cejas. – lukecampbell

+0

@lukecampbell Tiene que hacerlo. :) Considere este ejemplo: 'x = [- 1,1]' y 'map (lambda i: i> 0, x)'. Luego mira 'x' nuevamente. No cambió en absoluto. 'Map' creó una nueva lista. Y siempre lo hace. – freakish

+0

¿el mapa crea nuevas listas? No puedo creer que no haya estado considerando eso. – cammil

1

Creo que este es el problema con el uso del mapa() o la lista de las comprensiones.

No del todo.

my_things[:] = map(...) 
1

Puede usar el método __setattr__ para asignar el atributo en una lista de comprensión. Aunque, de acuerdo con algunos hilos SO, el uso de listas de comprensión sin utilizar el resultado no es pitónico.

[i.__setattr__('size', 'big') for i in my_things] 
9

Aunque estoy de acuerdo que no hay nada de malo en

for i in my_things: 
    i.size = "big" 

algunas personas están calientes en Python de una sola línea. ;)

Una opción es añadir un método set a su clase, que luego se puede llamar desde lambda (esencialmente ocultar la asignación de una función):

class Thing(object): 
    def setSize(self, size): 
     self.size = size 

map(lambda i: i.setSize("big"), my_things) 
+1

¡Esto aún crea una nueva lista! –

+0

Eso es cierto, pero eso no era un requisito. Dada la naturaleza de referencia por referencia de los objetos, también cambiará los objetos en la lista original. – DirkR

0

tal como esta en python3:

[dict(**i.__dict__, size='big') for i in my_things] 

o

map(lambda x: dict(**x.__dict__, size='big'), my_things) 

no si i es objeto dict

[dict(**i, size='big') for i in my_things] 

en python2

[dict(i.copy(), size='big') for i in my_things] # isinstance(i, dict) 
[dict(i.__dict__.copy(), size='big') for i in my_things] # isinstance(i, object) 
Cuestiones relacionadas