2

I know that PEP8 dictates to not assign lambda to an expression because it misses the entire point of a lambda function.

But what about a recursive lambda function? I've found that in many cases, it's really simple, clean and efficient to make a recursion with lambda assigning it to an expression instead of defining a function. And pep8 doesn't mention recursive lambda.

For example, let's compare a function that returns the greatest common divisor between two numbers:

def gcd(a,b):
    if b == 0:
        return a
    return gcd(b, a % b)

vs

gcd = lambda a, b: a if b == 0 else gcd(b, a % b)

So, what should I do?

Eugenio Herrera
  • 137
  • 1
  • 11
  • This only works with a small subset of recursive functions anyway, so why bother? – jonrsharpe Sep 24 '15 at 15:33
  • possible duplicate of [Which is more preferable to use in Python: lambda functions or nested functions ('def')?](http://stackoverflow.com/questions/134626/which-is-more-preferable-to-use-in-python-lambda-functions-or-nested-functions) – syntagma Sep 24 '15 at 15:36
  • Because it's more efficient and simple. You're right, it may be something very small but that's like the whole purpose of programming. Making something more efficient/simple. – Eugenio Herrera Sep 24 '15 at 15:38
  • But it's neither of those things. – jonrsharpe Sep 24 '15 at 15:43
  • Note that recursion in Python should generally be avoided, since Python does not optimize tail call recursion. So only use recursion when it's appropriate, eg traversing trees. Don't use it when a simple `while` loop will work. – PM 2Ring Sep 24 '15 at 15:44

3 Answers3

2

You have "cheated" a bit in your question, since the regular function could also be rewritten like this:

def gcd(a,b):
    return a if b == 0 else gcd(b, a % b)

Almost as short as the lambda version, and even this can be further squeezed into a single line, but at the expense of readability.

The lambda syntax is generally used for simple anonymous functions that are normally passed as arguments to other functions. Assigning a lambda function to a variable doesn't make much sense, it is just another way of declaring a named function, but is less readable and more limited (you can't use statements in it).

A lot of thought has been put into PEP8 and the recommendations in it are there for a reason, thus I would not recommend deviating from it, unless you have a very good reason for doing so.

plamut
  • 3,085
  • 10
  • 29
  • 40
  • You're right! I wasn't aware you could write functions in such a compressed way. I just tried this and worked: def f(a, b): return a if b == 0 else f(b, a % b) – Eugenio Herrera Sep 24 '15 at 15:48
  • 1
    @EugenioHerrera Just in case: Please don't start using one line function definitions everywhere. It simply harms readability, **line count doesn't matter**. – Markus Meskanen Sep 24 '15 at 17:00
1

Go with the normal function definition. There's absolutely no benefit of using lambda over def, and normal function definition is (for most people) much more readable. With lambda, you gain nothing, but you often lose readability.

I would recommend you to read this answer. Recursion doesn't change anything. In fact, in my opinion, it favours normal def even more.

Community
  • 1
  • 1
Markus Meskanen
  • 19,939
  • 18
  • 80
  • 119
-2

If you assign a lambda to a variable, you won't be able to pass it as an argument nor return it in the same line, which is the exact purpose of lambda.

Huazuo Gao
  • 1,603
  • 14
  • 20
  • 1
    This is not true. Functions are first-class objects in Python, whether created with `def` or `lambda`. – jonrsharpe Sep 24 '15 at 15:36
  • @jonrsharpe you cannot do something like `print(func = lambda: func())` – Huazuo Gao Sep 24 '15 at 15:41
  • @HuazuoGao You can't print any assignment at all: `print(x = 5)` also fails. And you can do `func = lambda: func()` just fine. – Markus Meskanen Sep 24 '15 at 16:29
  • @MarkusMeskanen That's my point. I'm just helping down-voters understand my answer. – Huazuo Gao Sep 25 '15 at 00:44
  • @HuazuoGao But you can't do that with normal functions either... Your point is irrelevant, you can still do `func = lambda: func(); print(func)` – Markus Meskanen Sep 25 '15 at 00:46
  • @MarkusMeskanen `print(lambda: func())` is good use of lambda, `func = lambda: func(); print(func)` is not. – Huazuo Gao Sep 25 '15 at 00:50
  • @HuazuoGao Yes, I know. That still doesn't make your answer valid. The question was about `def` vs `lambda` for recursive functions, you answered it by saying "you can't do this with lambda". Well, yeah, you can't do it with `def` either... Like I said, your point is irrelevant to the question, thus the downvotes (not by me) – Markus Meskanen Sep 25 '15 at 00:54
  • @MarkusMeskanen My logic is, If you get nothing with `lambda`, just use `def`. – Huazuo Gao Sep 25 '15 at 01:10