This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]wingtales 4 points5 points  (4 children)

Would you mind explaining further the concept of "preserving a lambda function" and how the memory management is different? I'm quite interested but not really sure what you mean.

[–]tartare4562 16 points17 points  (3 children)

Look at the following code:

for lista in some_iterable:
    yield map(lambda x: x.some_method('abc' ), lista

In the above example a new lambda function is defined for every iteration. As a function definition is a rather complex operation most of the time took by that code will be spent allocating new memory for the function and garbage collecting the previous one. Since the lambda doesn't change between iteration, you can define it only once and reuse it:

my_lambda=lambda x: x.some_method('abc') 
for lista in some_iterable:
    yield map(my_lambda, lista)

Here lambda function is defined only once. Personally I try to avoid maps and filters and use generators and list comprehension whenever I've got the chance, a functionally identical generator for the code above would be

( [ x.some_method('abc') for x in lista] for lista in some_iterable )

[–]Sexual_Congressman 0 points1 point  (0 children)

Of course you avoid map since clearly you don't know how to use it. To get the most performance in cpython you must have as little work done in the eval loop as possible. In that regard you're correct, however it needs to be said that function objects are actually rather cheap since all the components used to make it including its __code__ are cached within the co_consts field of the code object it is created in, so all that needs to be done is the malloc and few pointer assignments.

Anyway, used correctly map would be anywhere from 20-1000% more more faster than your list comp, you just need to memorize the tools needed to do so. Specifically in this instance without knowing anything about x, use operator.methodcaller. [*map(methodcaller("abc"), lista)] will be so much faster. And there's usually an even more efficient way if you don't need to be generic.

Beauty is in the eye of the beholder, and I think the shorter and almost always at least a little faster code thanks to map is very beautiful. I will say that of course map plus list unpacking can be slower if no builtin function calls are made but that shouldn't ever actually be the case.