如何调用对象列表的相同方法?
假设这样的代码:
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)