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 lambda
s 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
How to Do Assignments in a List Comprehension
In-Memory Size of a Python Structure
Special (Magic) Methods in Python
Python Dictionary Keys. "In" Complexity
Nested Dictionary to Multiindex Dataframe Where Dictionary Keys Are Column Labels
Executing Multiple Statements with Postgresql via SQLalchemy Does Not Persist Changes
Getting Rid of Console Output When Freezing Python Programs Using Pyinstaller
Interpolate Nan Values in a Numpy Array
It Is More Efficient to Use If-Return-Return or If-Else-Return
Why Sum on Lists Is (Sometimes) Faster Than Itertools.Chain
Python Read from Subprocess Stdout and Stderr Separately While Preserving Order
Pil: Convert Bytearray to Image
Is There a "Not Equal" Operator in Python
List() Uses Slightly More Memory Than List Comprehension
How to Improve the Label Placement in Scatter Plot