Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Idiomatic way to call method on all objects in a list of objects Python 3

I have a list of objects and they have a method called process. In Python 2 one could do this

map(lambda x: x.process, my_object_list)

In Python 3 this will not work because map doesn't call the function until the iterable is traversed. One could do this:

list(map(lambda x: x.process(), my_object_list))

But then you waste memory with a throwaway list (an issue if the list is big). I could also use a 2-line explicit loop. But this pattern is so common for me that I don't want to, or think I should need to, write a loop every time.

Is there a more idiomatic way to do this in Python 3?

like image 916
Neil Avatar asked Jul 25 '18 13:07

Neil


People also ask

How do you call a function for each item in a list Python?

The best way to apply a function to each element of a list is to use the Python built-in map() function that takes a function and one or more iterables as arguments. It then applies the function to each element of the iterables. An alternate way is to use list comprehension.

Which methods can be used with list objects?

Decode, Pop, Clear.

Which of the following statement retrieves names of all built-in objects in Python?

Check with the built-in function dir() You can get a list of names of built-in objects, such as built-in functions and constants, by passing the builtins module or __builtins__ to dir() . To make the output easier to read, use pprint.

How do you call a method object?

To call an object's method, simply append the method name to an object reference with an intervening '. ' (period), and provide any arguments to the method within enclosing parentheses. If the method does not require any arguments, just use empty parentheses.


1 Answers

Don't use map or a list comprehension where simple for loop will do:

for x in list_of_objs:
    x.process()

It's not significantly longer than any function you might use to abstract it, but it is significantly clearer.

Of course, if process returns a useful value, then by all means, use a list comprehension.

results = [x.process() for x in list_of_objs]

or map:

results = list(map(lambda x: x.process(), list_of_objs))

There is a function available that makes map a little less clunky, especially if you would reuse the caller:

from operator import methodcaller
processor = methodcaller('process')
results = list(map(processor, list_of_objs))
more_results = list(map(processor, another_list_of_objs))

If you are looking for a good name for a function to wrap the loop, Haskell has a nice convention: a function name ending with an underscore discards its "return value". (Actually, it discards the result of a monadic action, but I'd rather ignore that distinction for the purposes of this answer.)

def map_(f, *args):
    for f_args in zip(*args):
        f(*f_args)

# Compare:
map(f, [1,2,3])  # -- return value of [f(1), f(2), f(3)] is ignored
map_(f, [1,2,3])  # list of return values is never built
like image 95
chepner Avatar answered Sep 27 '22 23:09

chepner