2012-05-11 110 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'。它根本没有改变。 'Map'创建了新的列表。它总是如此。 – freakish

+0

地图是否会创建新列表?我不敢相信我没有考虑过这个。 – cammil

1

我认为这是使用map()或列表解析的问题。

不完全是。

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

您可以使用__setattr__方法在列表理解中分配属性。尽管根据一些SO线程,使用列表推导而不使用输出并不是pythonic。

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

虽然我同意,有什么错

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

有些人是热成蟒蛇单行。 ;)

一种选择是一套方法添加到您的类,然后可以从拉姆达称为(实质上隐藏在一个函数赋值):上python3

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

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

这仍然创建一个新的列表! –

+0

的确如此,但那不是要求。鉴于对象的引用性质,它也会改变原始列表中的对象。 – DirkR

0

也许是这样的:

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

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

如果i是字典不反对

[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) 
相关问题