Python Learning Notes -- Anonymous Functions

Keywords: Lambda Python Java

Anonymous function

Definition

When defining ordinary functions, the following are used:

def fn():
    pass

Anonymous functions are functions without names. They are defined by the keyword lambda, followed by a parameter x, then separated by a colon, and then a function body is defined as follows:

>>> lambda x: x + 1
<function <lambda> at 0x0000027FC94F7288>

There is no line change after the colon. This is the difference between python and js and java.
We can enclose the parameters in parentheses and put them in the back parentheses as follows:

>>> (lambda x: x + 1)(3)
4

In an anonymous function, x+1 is our last statement, so the anonymous function returns the value of the last statement.

The characteristics of anonymous functions:

  • Definition with lambda
  • The parameter list does not need to be enclosed in parentheses
  • A colon is not used to open a new block of statements
  • The last expression has no return statement, and the value of the last expression is the return value.

Call of anonymous functions

The entire function expression can be assigned to a variable f:

>>> f = lambda x: x + 1
>>> f
<function <lambda> at 0x0000027FC94F7288>
>>> f(5)
6

As the whole process above, it is very convenient to call the function.

limit

Anonymous functions (lambda expressions) can only be written on one line, so they are also called one-line functions.
The following are some usages:

#Call directly with 0
>>> f = lambda : 0
>>> f()
0
#Multiple parameters
>>> (lambda x, y: x + y)(3, 5)
8
#Default parameters
>>> (lambda x, y=3: x + y)(2)
5
#Variable position parameters
>>> (lambda *args: args)(*range(3))
(0, 1, 2)
#Keyword Variable Parameters
>>> (lambda *args, **kwargs: print(args, kwargs))(*range(3), **{str(x):x for x in range(3)})
(0, 1, 2) {'0': 0, '1': 1, '2': 2}
#keyword-only parameter
>>> (lambda *, x: x)(x=3)
3

Normal functions support parameter changes, and anonymous functions support them.

Application of Anonymous Functions

sorted

>>> help(sorted)
Help on built-in function sorted in module builtins:

sorted(iterable, /, *, key=None, reverse=False)
    Return a new list containing all items from the iterable in ascending order.
    
    A custom key function can be supplied to customize the sort order, and the
    reverse flag can be set to request the result in descending order.

Pass an iteratable object to sorted, key defaults to None, and reverse represents whether or not to invert.

Suppose you have a User object with name and age attributes:

from collections import namedtuple

User = namedtuple('User',['name','age'])
users = [User('kidult', 18), User('punch', 16)]

At this point, we want to sort users by age. If there is no anonymous function, we need to define a function first.

def get_age(user):
    return user.age

#Pass in a users object to the sorted function and pass the key value to sort the age s
>>> sorted(users,key=get_age)
[User(name='punch', age=16), User(name='kidult', age=18)]

#Anonymous function version
>>> sorted(users, key=lambda x: x.age)
[User(name='punch', age=16), User(name='kidult', age=18)]

map

>>> help(map)
Help on class map in module builtins:

class map(object)
 |  map(func, *iterables) --> map object
 |
 |  Make an iterator that computes the function using arguments from
 |  each of the iterables.  Stops when the shortest iterable is exhausted.
 |
 |  Methods defined here:
 |
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |
 |  __iter__(self, /)
 |      Implement iter(self).
 |
 |  __next__(self, /)
 |      Implement next(self).
 |
 |  __reduce__(...)
 |      Return state information for pickling.
 |
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.

One iteration for each iteratable object

>>> map(lambda x: x.age,users)
<map object at 0x0000027FC98C1688>
>>> list(map(lambda x: x.age, users))
[18, 16]

filter

>>> help(filter)
Help on class filter in module builtins:

class filter(object)
 |  filter(function or None, iterable) --> filter object
 |
 |  Return an iterator yielding those items of iterable for which function(item)
 |  is true. If function is None, return the items that are true.
 |
 |  Methods defined here:
 |
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |
 |  __iter__(self, /)
 |      Implement iter(self).
 |
 |  __next__(self, /)
 |      Implement next(self).
 |
 |  __reduce__(...)
 |      Return state information for pickling.
 |
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.

Each iteratable object is passed in. If the function returns True, it exists. If it returns False, it does not exist. As follows:

>>> list(filter(lambda x: x.age < 17, users))
[User(name='punch', age=16)]

The following are the prototypes of map and filter:

def _map(fn, it):
    return (fn(x) for x in it)

def _filter(fn, it):
    return (x for x in it if fn(x))

Summary

These methods are still very useful, especially filters.

Posted by dclamp on Wed, 24 Jul 2019 01:31:44 -0700