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?
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.
Decode, Pop, Clear.
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With