E731 Do Not Assign a Lambda Expression, Use a Def

E731 do not assign a lambda expression, use a def

The recommendation in PEP-8 you are running into is:

Always use a def statement instead of an assignment statement that
binds a lambda expression directly to a name.

Yes:

def f(x): return 2*x 

No:

f = lambda x: 2*x 

The first form means that the name of the resulting
function object is specifically 'f' instead of the generic '<lambda>'.
This is more useful for tracebacks and string representations in
general. The use of the assignment statement eliminates the sole
benefit a lambda expression can offer over an explicit def statement
(i.e. that it can be embedded inside a larger expression)

Assigning lambdas to names basically just duplicates the functionality of def - and in general, it's best to do something a single way to avoid confusion and increase clarity.

The legitimate use case for lambda is where you want to use a function without assigning it, e.g:

sorted(players, key=lambda player: player.rank)

In general, the main argument against doing this is that def statements will result in more lines of code. My main response to that would be: yes, and that is fine. Unless you are code golfing, minimising the number of lines isn't something you should be doing: go for clear over short.

PEP 8 warning Do not use a lambda expression use a def for a defaultdict lambda expression

A lambda in Python is essentially an anonymous function with awkward restricted syntax; the warning is just saying that, given that you are assigning it straight to a variable - thus giving the lambda a name -, you could just use a def, which has clearer syntax and bakes the function name in the function object, which gives better diagnostics.

You may rewrite your snippet as

def dct_structure():
return defaultdict(dct_structure)

dct = dct_structure()

Auto-PEP8 is adding lines by turning my lambda into def function, how do I disable this specific auto format?

This is triggered by the pycodestyle code E731

You can disable this with --ignore=E731

In a config file (for instance tox.ini / setup.cfg):

[pep8] 
ignore=E731

Can i use a lambda expression here?

Before thinking about how you'd write a lambda function for this, consider how you'd write a normal function. It would probably look something like this:

def day_of_return(starting_day, length_of_stay):
return (starting_day + length_of_stay) % 7

Then you can easily convert this to a lambda function:

day_of_return = lambda starting_day, length_of_stay: (starting_day + length_of_stay) % 7

or, with shorter variable names:

day_of_return = lambda s,l: (s+l) % 7

And then you could call it like this:

print(day_of_return(3,10))

Edit: In the comments, @daragua points out that assigning lambdas to a variable kind of defeats the purpose of a lambda, so you can also remove the assignment altogether:

print((lambda s,l: (s+l) % 7) (3,10)) # This will print 6

Correct usage of lambda functions with Pycodestyle

I would not recommend you to ignore such warning. In case you really want to do that, you can just configure Flake8 to ignore the rule E731.

Add this to your project's configuration file:

[flake8]
ignore = E731

Lambdas in general are allowed. What flake8 recommends against is assigning a name to a lambda (anonymous) function.

python lambda : maximum recursion depth exceeded in comparison

When you write func = lambda x : func(x), you are redefining func to be that lambda, which just calls itself repeatedly until it bottoms out at the recursion limit. Consider a def version of the same:

def i_call_myself_forever(x):
return i_call_myself_forever(x)

Your lambda is doing the same thing.

I think what you are trying to do is call the first definition of func from the second. That being the case, just give them distinct names and you'll be fine.

Additionally, you're not correctly understanding what func = lambda x : lambda x : x * 2 means. What's happening is that the top level lambda is returning another lambda, namely lambda x : x * 2. That second level lambda uses the same parameter name x and as such shadows the x from the top level lambda. You could call it as follows

func = lambda x : lambda x : x * 2
intermediate_func = func(5) # 5 is captured but never used
assert intermediate_func(6) == 12 # this is calling lambda x : x * 2

Let's also try a def version to be as clear as possible:

def i_return_a_function(x):
def im_an_inner_function(x):
# my x shadows i_return_a_function's x
return x * 2
return im_an_inner_function # notice how i_return_a_function's x is never used

Finally, I want to emphasize @tdelaney's comment: Sure, there are plenty of examples of people assigning lambdas to a name out there in the wild, but that doesn't mean that doing so is considered good practice. There's some disagreement in the community about how strict to be about this, but my rule of thumb is to only use lambda when the function is a single expression (which is all you can express with a python lambda) that I'm using exactly once.



Related Topics



Leave a reply



Submit