如何调用对象列表的相同方法?

假设这样的代码:

class Base: def start(self): pass def stop(self) pass class A(Base): def start(self): ... do something for A def stop(self) .... do something for A class B(Base): def start(self): def stop(self): a1 = A(); a2 = A() b1 = B(); b2 = B() all = [a1, b1, b2, a2,.....] 

现在我想调用方法开始和停止(也许还有其他)列表中的每个对象。 有没有什么优雅的方式来做这个,除了写一堆函数之外

 def start_all(all): for item in all: item.start() def stop_all(all): 

* _all()函数非常简单,只需要编写几个函数即可。 如果你有很多相同的function,你可以写一个通用的函数:

 def apply_on_all(seq, method, *args, **kwargs): for obj in seq: getattr(obj, method)(*args, **kwargs) 

或者创build一个function工厂:

 def create_all_applier(method, doc=None): def on_all(seq, *args, **kwargs): for obj in seq: getattr(obj, method)(*args, **kwargs) on_all.__doc__ = doc return on_all start_all = create_all_applier('start', "Start all instances") stop_all = create_all_applier('stop', "Stop all instances") ... 

这将工作

 all = [a1, b1, b2, a2,.....] map(lambda x: x.start(),all) 

简单的例子

 all = ["MILK","BREAD","EGGS"] map(lambda x:x.lower(),all) >>>['milk','bread','eggs'] 

和python3

 all = ["MILK","BREAD","EGGS"] list(map(lambda x:x.lower(),all)) >>>['milk','bread','eggs'] 

似乎这样做会有更多的Pythonic方式,但我还没有find它。

如果我在一堆对象上调用相同的函数(而不是方法),我有时会使用“map”

 map(do_something, a_list_of_objects) 

这取代了一堆看起来像这样的代码:

  do_something(a) do_something(b) do_something(c) ... 

但是也可以用行人“for”循环来实现:

  for obj in a_list_of_objects: do_something(obj) 

缺点是a)你正在创build一个列表作为“map”的返回值,这只是被抛弃了,b)它可能更容易混淆,只是简单的循环变体。

你也可以使用列表理解,但也有点滥用(再一次,创build一个丢弃列表):

  [ do_something(x) for x in a_list_of_objects ] 

对于方法,我想这些都可以工作(与相同的保留):

 map(lambda x: x.method_call(), a_list_of_objects) 

要么

 [ x.method_call() for x in a_list_of_objects ] 

所以,实际上,我认为行人(还是有效的)“for”循环可能是你最好的select。

该方法

 for item in all: item.start() 

简单,易读,简洁。 这是Python为此操作提供的主要方法。 你当然可以把它封装在一个函数中,如果有帮助的话。 为这个通用定义一个特殊的函数可能并不像写出for循环那样清晰。

也许map ,但既然你不想列出,你可以写自己的…

 def call_for_all(f, seq): for i in seq: f(i) 

那么你可以这样做:

 call_for_all(lamda x: x.start(), all) call_for_all(lamda x: x.stop(), all) 

顺便说一下,全部是内置函数,不要覆盖它;-)

采取@Ants Aasmas进一步回答,您可以创build一个包装,它可以接受任何方法调用,并将其转发给给定列表的所有元素:

 class AllOf: def __init__(self, elements): self.elements = elements def __getattr__(self, attr): def on_all(*args, **kwargs): for obj in self.elements: getattr(obj, attr)(*args, **kwargs) return on_all 

那个类可以像这样使用:

 class Foo: def __init__(self, val="quux!"): self.val = val def foo(self): print "foo: " + self.val a = [ Foo("foo"), Foo("bar"), Foo()] AllOf(a).foo() 

其中产生以下输出:

  foo:foo
 foo:酒吧
 foo:quux! 

通过一些工作和独创性,可以增强处理属性(返回属性值列表)。

有一个更简单的方法:

 map(methodcaller('stop'), all)