How to call same method for a list of objects?

Suppose code like this:

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

Now I want to call methods start and stop (maybe also others) for each object in the list all. Is there any elegant way for doing this except of writing a bunch of functions like

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

def stop_all(all):

This will work

all = [a1, b1, b2, a2,.....]

map(lambda x: x.start(),all)    

simple example

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

and in python3

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

It seems like there would be a more Pythonic way of doing this, but I haven't found it yet.

I use "map" sometimes if I'm calling the same function (not a method) on a bunch of objects:

map(do_something, a_list_of_objects)

This replaces a bunch of code that looks like this:

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

But can also be achieved with a pedestrian "for" loop:

  for obj in a_list_of_objects:
       do_something(obj)

The downside is that a) you're creating a list as a return value from "map" that's just being throw out and b) it might be more confusing that just the simple loop variant.

You could also use a list comprehension, but that's a bit abusive as well (once again, creating a throw-away list):

  [ do_something(x) for x in a_list_of_objects ]

For methods, I suppose either of these would work (with the same reservations):

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

or

[ x.method_call() for x in a_list_of_objects ]

So, in reality, I think the pedestrian (yet effective) "for" loop is probably your best bet.


The approach

for item in all:
    item.start()

is simple, easy, readable, and concise. This is the main approach Python provides for this operation. You can certainly encapsulate it in a function if that helps something. Defining a special function for this for general use is likely to be less clear than just writing out the for loop.


maybe map, but since you don't want to make a list, you can write your own...

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

then you can do:

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

by the way, all is a built in function, don't overwrite it ;-)


Starting in Python 2.6 there is a operator.methodcaller function.

So you can get something more elegant (and fast):

from operator import methodcaller

map(methodcaller('method_name'), list_of_objects)