2012-05-11 4 views
10

Я хочу применить функцию ко всем элементам в списке, но я хочу фактически изменить элементы (объекты), а не просматривать результаты. Я думаю, что это проблема с использованием map() или списком понятий.Как применить функцию к элементам списка?

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" 

Каков способ сделать это?

ответ

13

А что случилось с

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

Вы не хотите использовать ни map, ни списка comprehansion, потому что они на самом деле создавать новые списки. И тебе не нужно это накладные расходы, не так ли?

+0

Я не знал, что карта сделал новый список, который поднимая некоторые брови. – lukecampbell

+0

@lukecampbell Он должен. :) Рассмотрим этот пример: 'x = [- 1,1]' и 'map (lambda i: i> 0, x)'. Затем снова посмотрите на 'x'. Это совсем не изменилось. «Карта» создала новый список. И это всегда так. – freakish

+0

карта создает новые списки? Я не могу поверить, что я об этом не думал. – cammil

1

Я думаю, что это проблема использования карт() или списков.

Не совсем.

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

Вы можете использовать метод __setattr__ для назначения атрибута в понимании списка. Хотя, согласно некоторым SO-потокам, использование списков без использования вывода не является питоновым.

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

Хотя я согласен, что нет ничего плохого в

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

некоторые люди горячи в питона Однострочники. ;)

Один из вариантов, чтобы добавить метод набора в класс, который затем может быть вызван из лямбда (по существу, скрывая назначение в функции):

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

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

Это все еще создает новый список! –

+0

Это правда, но это не было требованием. Учитывая ссылочный характер объектов, он также изменит объекты в исходном списке. – DirkR

0

может быть, как это на Python3:

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

или

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

, если я это ДИКТ не возражает

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

на 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) 
Смежные вопросы