Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
lambda or operator?
#1
So, say you are passing around callables to functions. Say also that you could do this with something from the operator package. Would you create a lambda to do it, or use operator?

For example, I have this function specification:

def ask_valid(self, prompt, valid, default = '', conversion = lambda choice: choice.lower()):
But I was thinking of rewriting it this way:

def ask_valid(self, prompt, valid, default = '', conversion = operator.methodcaller('lower')):
Do you have a preference? Any particular reason for that preference?
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#2
I found some thoughts about this here.

If you look at the operator module sources, you find that methodcaller is a light-weight class. In any case,
using it, you implicitly include additional code to be executed. This, in turn, can slightly increase the time of execution.

Using lambda keyword is redundant in this case, str.lower is shorter.

Lets look at benchmarks:

from operator import methodcaller

def ask_valid1(x, conversion=lambda choice: choice.lower()):
    return conversion(x)

def ask_valid2(x, conversion=methodcaller('lower')):
    return conversion(x)

def ask_valid3(x, conversion=str.lower):
    return conversion(x)
%timeit ask_valid1('Name')
Output:
321 ns ± 1.88 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit ask_valid2('Name')
Output:
346 ns ± 2.76 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit ask_valid3('Name')
Output:
317 ns ± 2.87 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
So, str.lower looks more pythonic in this case (and is fastest solution).

Finally, if you have several methods,
where the conversion argument should have default value (a function),
I would suggest to define something like _default_conversion function, e.g.

def _default_conversion(x):
    return x.lower()

#OR 

_default_conversion = str.lower
    
class A:

    def ask_valid(self, *args, conversion=_default_conversion):
        pass

    def ask_invalid(self, *args, conversion=_default_conversion):
        pass
This allows to manage all method defaults (conversions) in one place and also might be useful when debugging.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020