如何对一系列对象调用同一方法?

106 投票
10 回答
140448 浏览
提问于 2025-04-15 21:52

假设有这样的代码:

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,.....]

现在我想对列表中的每个对象调用 start 和 stop 方法(可能还有其他方法)。有没有什么简单优雅的方法来做到这一点,而不是写一堆函数,比如:

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

def stop_all(all):

10 个回答

42

看起来应该有更符合Python风格的方法来做这个,但我还没找到。

有时候我会用“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) 你用“map”创建了一个列表作为返回值,但这个列表其实没用就被丢掉了;b) 可能比简单的循环更让人困惑。

你也可以用列表推导式,但这也有点过分(同样是创建了一个没用的列表):

  [ 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”循环可能是最好的选择。

201

这个方法可以用

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']
8

*_all() 函数非常简单,对于一些方法,我干脆就自己写函数。如果你有很多功能完全相同的函数,可以写一个通用的函数:

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

或者可以创建一个函数工厂:

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")
...

撰写回答