In addition to def statements, Python provides an expression form for generating function objects. It is called lambda because of its similarity to a tool in the LISP language. Like def, this expression creates a function that can be called later, but it returns a function rather than assigning the function to a variable name. This is why lambdas are sometimes called anonymous functions. In fact, they are often used in a form of inline function definition, or as a way to defer the execution of some code.

Lambda expressions

The general form of lambda is the keyword lambda, followed by one or more arguments (much like a parenthesized argument list in the def header), followed by a colon, followed by an expression:

Lambda Argument1, Argument2,… ArgumentN: expression using argument

六四运动

Function objects returned by lambda expressions work exactly the same as function objects created and copied by def, but lambda has some differences that make it useful for specific roles.

  • Lambda is an expression, not a statement. Because of this, lambda can appear in places where Python syntax does not allow def — for example, in a list constant or in the arguments of a function call. In addition, as an expression, lambda returns a value (a new function) that can optionally be assigned to a variable name. In contrast, def statements always assign a new function to a variable name in the header rather than return the function as a result.
  • The body of a lambda is a single expression, not a block of code. The body of the lambda is as simple as the code placed in the return statement of the def body. Simply write the result as a smooth expression rather than an explicit return. Because it is limited to expressions, lambda is usually smaller than def: you can encapsulate only limited logic in the body of the lambda, not even statements like if. This is by design — it limits program nesting: Lambda is designed to write simple functions, while DEF is designed to handle larger tasks.

Despite these differences, def and Lambda can both do the same kind of work. For example, we saw how to create functions using def statements.

# # # # # # # # # # # # # # # # # # # # # # # ordinary function # # # # # # # # # # # # # # # # # # # # # # # define functions (common mode) def func (arg) : Return arg + 1 result = func(123)Copy the code

However, you can achieve the same effect using lambda expressions by explicitly assigning the result to a variable name from which you can then call the function.

# # # # # # # # # # # # # # # # # # # # # # # lambda # # # # # # # # # # # # # # # # # # # # # # # define functions (lambda expressions) my_lambda = lambda arg: Arg + 1 # result = my_lambda(123)Copy the code

Here f is assigned to a function object created by a lambda expression. This is what def does, except that the assignment to def is automatic.

Default arguments can also be used in lambda arguments, just as they are in DEF.

>>> x = (lambda a="fee", b="fie", c="foe": a + b + c)
>>> x("wee")
'weefiefoe'
Copy the code

Code in a lambda body follows the same rules of action on lookups as code in def. A local scope introduced by lambda expressions is more like a nested DEF statement and will automatically look up variable names from upper-level functions, modules, and built-in scopes (via LEGB rules).

>>> def knights():
...    title = "Sir"
...    action = (lambda x: title + ' ' + x)
...    return action
...
>>> act = knight()
>>> act('robin')
'Sir robin'
Copy the code

In Python 2, the value of the variable name title is usually modified to be passed in as the value of the default argument.

Why lambda

In general, lambda acts as a kind of function sketch, allowing the definition of a function to be embedded within the code being used. They are completely optional (you can always use def instead), but they lead to a cleaner code structure in cases where you only need to embed small pieces of executable code.

For example, the callback handler, which we’ll see later, is often written as a single-line lambda expression in the argument list of a registration call, rather than defined using a def elsewhere in the file and then referring to that variable name.

Lambda is commonly used to write jump tables, which are lists or dictionaries of actions that can be performed as needed. This is shown in the following code.

L = [lambda x: x**2,
     lambda x: x**3,
     lambda x: x**4]
 
for f in L:
    print(f(2))            # prints 4, 8, 16
     
print(L[0](3))             # prints 9
Copy the code

Lambda expressions are most useful as a shorthand for DEF when small pieces of executable code need to be written into places where def statements cannot be written syntactically. This code snippet, for example, can create a list of three functions by embedding a lambda expression in a list constant. A def does not work in a list constant because it is a statement, not an expression. Equivalent DEF code may need to have temporary function names and function definitions outside the context in which it is intended to be used.

def f1(x): return x**2
def f2(x): return x**3
def f3(x): return x**4
 
L = [f1, f2, f3]
 
for f in L:
    print(f(2))            # prints 4, 8, 16
     
print(L[0](3))             # prints 9
Copy the code

In fact, we can use dictionaries or other data structures in Python to build more kinds of behavior tables to do the same thing. Here is another example given in interactive prompt mode:

>>> key = 'got'
>>> {'already': (lambda: 2 + 2),
...  'got':     (lambda: 2 * 4),
...  'one':     (lambda: 2 ** 6)}[key]()
8
Copy the code

Here, when Python uses the dictionary, each nested lambda generates and leaves a function that can be called later. One of the functions is retrieved through the key index, and the parentheses cause the removed function to be called. Writing code this way makes dictionaries a more versatile multiway branching tool than the extended use of the if statement I showed you earlier.

If lambda is not used to do this, def statements that appear elsewhere in the three files need to be used instead, somewhere outside the dictionary where the functions will be used.

>>> def f1(): return 2 + 2
...
>>> def f2(): return 2 * 4
...
>>> def f3(): return 2 ** 6
...
>>> key = 'one'
>>> {'already': f1, 'got': f2, 'one': f3}[key]()
64
Copy the code

Again, the same functionality is implemented, but defs may appear anywhere in the file, even if they are followed by very little code. The lambda-like code provides a particularly useful class of functions that can occur in a single case: if the three functions here are not used elsewhere, it makes sense to embed their definitions as lambda in the dictionary. Not only that, but the DEF format requires the creation of variable names for these small functions, which may (or may not, but is always possible) conflict with other variable names in the file.

How to (not) make Python code obscure

Since the body of a lambda must be an expression (and not statements), it follows that only a limited amount of logic can be encapsulated into a lambda. If you know what you’re doing, you can write enough statements in Python as expressions equivalent.

For example, if you want to print in a lambda function, write the expression sys.stdout.write(STR (x) + “\n”) directly instead of using statements like print(x). Similarly, to escape logic in a lambda, you can use if/else ternary expressions, or equivalent but tricky combinations of and/or. As we saw earlier, the following statement:

if a:
    b
else:
    c
Copy the code

Can be simulated by the following generalized equivalent expression:

b if a else c
((a and b) or c)
Copy the code

Because such similar expressions can be placed in lambda, they can be used to implement selection logic in lambda functions.

>>> lower = (lambda x, y: x if x < y else y)
>>> lower('bb', 'aa')
'aa'
>>> lower('aa', 'bb')
'aa'
Copy the code

In addition, if you need to perform a loop in a lambda function, you can embed tools like map calls or list-resolution expressions to do so.

>>> import sys >>> showall = lambda x: list(map(sys.stdout.write, x)) >>> t = showall(['spam\n', 'toast\n', 'eggs\n']) spam toast eggs >>> showall = lambda x: Write (line) for line in x] # list parsing >>> t = showall(['spam\n', 'toast\n', 'eggs\n']) spam toast eggsCopy the code

These techniques should only be used as a last resort. If not carefully, they can lead to unreadable (and thus obscure) Python code. In general, brevity is better than complexity, clarity is better than obscurity, and a complete statement is better than an arcane expression. That’s why lambda is limited to expressions. If you have more responsible code to write, use def, lambda for a smaller piece of inline code. On the other hand, you’ll also find it useful to use these techniques with humidity.

Nested lambda and scope

Lambda is the biggest beneficiary of nested function scoping look-ups (E in LEGB). For example, in the following example, the lambda appears in def (typically), and when the mall function is called, the nested lambda gets the value of the variable name X in the upper function scope.

>>> def action(x):
    return (lambda y: x + y)
 
>>> act = action(99)
>>> act
<function action.<locals>.<lambda> at 0x0000014EF59F4C80>
>>> act(2)
101
Copy the code

What was left unsaid in the previous discussion of nested function scopes is that lambdas can also get variable names in any of the upper lambdas. This situation is a bit subtle, but imagine if the high def in our last example was replaced with a lambda.

>>> action = (lambda x:(lambda y: x + y))
>>> act = action(99)
>>> act(3)
102
>>> ((lambda x: (lambda y: x + y))(99))(4)
103
Copy the code

The nested lambda structure here lets the function create a function when called. In either case, the nested lambda code can retrieve the variable X in the upper lambda function. This works, but the code is rather convoluted. For readability purposes, it is generally best to avoid using nested lambdas.