2

So I'm trying to understand how the use of * in the lambda example below fits within the *arg/**kwarg Python idioms.

If I create a simple function, summing, that uses sum(iterable) to sum a list of numbers, there's at least a couple ways to do it.

def summing(*x): return sum(*x)

or I've seen other code which uses this version for lambda

summing = lambda * x: sum(*x)

For the lambda version, I don't really understand how the * symbol fits into the idiom. I'm assuming that it's not meant to be a glob pattern -- so what is it? Is it used elsewhere in Python? (Or is something like "*args" whitespace insensitive?)

(This question started with a little snippet of code that stumped me.)

Community
  • 1
  • 1
jay-tyler
  • 45
  • 4
  • 6
    yes, `*args` is whitespace insensitive. `* args` is the exact same thing. – mhlester Apr 23 '14 at 18:30
  • Ok. That's a little bit annoying. The trimmed version is preferred? – jay-tyler Apr 23 '14 at 18:33
  • 2
    PEP 8 hasn't made any proclamations yet, but just about *everyone* uses `*args` and `**kw` (no whitespace between the asterisks and the argument name). – Martijn Pieters Apr 23 '14 at 18:34
  • 1
    @iasonas - PEP 8 _has_ stated though that it is a [bad practice](http://legacy.python.org/dev/peps/pep-0008/#programming-recommendations) to make functions using `lambda` like that. Instead, you should use `def`, like in your first example. –  Apr 23 '14 at 18:38
  • Thanks. I've read through PEP 8, and know better than to code the lambda version myself, but I wanted to understand what was going on here. Because PEP 8 is silent about arg/kwarg whitespace, I thought maybe this was something different than *args/**kwargs (or some kind of extension of the idiom)... – jay-tyler Apr 23 '14 at 18:42

1 Answers1

0
summing = lambda *x: sum(*x)

is basically the same as

def summing(*x): return sum(*x)

but functions are prefered, as they are more readable and a bit faster.

However, you shouldn't use either of the above code snippets. *x allows for a variable amount of arguments, only to unpack them for sum().

If you want to pass your summing() function arguments like this:

summing(1,2,3,4)

... use the following code:

def summing(*x): return sum(x)

If you want to give it a sequence instead...

summing([1,2,3,4])

... use this:

def summing(x): return sum(x)

Your variant...

def summing(*x): return sum(*x)

... requires a sequence to be passed (like the function above, hence you don't need *x twice!), you can't give it (1,2,3,4). sum() takes an iterable as first argument, the second is for a start value. sum(*x) will throw errors at you.

Community
  • 1
  • 1
CodeManX
  • 11,159
  • 5
  • 49
  • 70
  • 1
    speed is not the reason, not to use lambdas. Also, I think `sum` is just an example i.e., the actual usage inside the function doesn't matter. Otherwise `summing = sum` is simpler and more effective. – jfs Apr 23 '14 at 20:41
  • ... or even simpler: `sum(...)` without a function alias. BTW: Guido is against lambdas. – CodeManX Apr 23 '14 at 21:29
  • using just `sum` might be incorrect for the same reasons `typedef` exists in C. – jfs Apr 23 '14 at 21:34
  • @Andy Hayden fixed [his benchmark](http://stackoverflow.com/a/11988012/2044940). Now `def` and `lambda` version have essentially the same speed. Though there are other reasons not to use lambdas (that is what I meant in the first comment). – jfs Apr 24 '14 at 01:22