table of Contents
Higher order function
Variables can point to functions, and the function itself can also be assigned to variables , that is: variables can point to functions
>>> f = abs
>>> f(-10)
10
The function name is also a variable , the function name is actually the variable that points to the function
A function can receive another function as a parameter, this function is called a higher-order function
#一个最简单的高阶函数:
def add(x, y, f):
return f(x) + f(y)
The derivation process when calling the above function is as follows
x = -5
y = 6
f = abs
f(x) + f(y) ==> abs(-5) + abs(6) ==> 11
return 11
map/reduce
map()
The function receives two parameters, one is a function, and the other is Iterable
to map
apply the passed function to each element of the sequence in turn, and return the result as a new one Iterator
.
>>> def f(x):
... return x * x
...
>>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> list(r)
[1, 4, 9, 16, 25, 36, 49, 64, 81]
map()
The first parameter passed in f
is the function object itself. Since the result r
is one Iterator
, it Iterator
is a lazy sequence, so list()
let it calculate the entire sequence through a function and return a list
reduce(function, sequence, initializer=None) applies a function to a sequence[x1, x2, x3, ...]
, this function must receive two parameters, andreduce
the result continues to be accumulated with the next element of the sequence.
- If the optional parameter initializer is provided, it is equivalent to inserting it as an element of the sequence into the first part of the sequence
The effect is:
For example, to sum a sequence:
>>> from functools import reduce
>>> def add(x, y):
... return x + y
>>> reduce(add, [1, 3, 5, 7, 9])
25
If we consider that a string str
is also a sequence, with a slight modification to the above example map()
, we can write a function to str
convert toint
:
>>> from functools import reduce
>>> def fn(x, y):
... return x * 10 + y
>>> def char2num(s):
... digits = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
... return digits[s]
>>> reduce(fn, map(char2num, '13579'))
13579
str2int
The function organized into one is:
from functools import reduce
DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
def str2int(s):
def fn(x, y):
return x * 10 + y
def char2num(s):
return DIGITS[s]
return reduce(fn, map(char2num, s))
You can also use lambda functions to further simplify:
from functools import reduce
DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
def char2num(s):
return DIGITS[s]
def str2int(s):
return reduce(lambda x, y: x * 10 + y, map(char2num, s))
filter(
function, iterable)
Used to filter the sequence
filter()
It also receives a function and a sequence. The map()
difference is that filter()
the passed function acts on each element in turn, and then decides True
whether False
to keep or discard the element according to the return value . To delete the empty string in a sequence, you can write:
def not_empty(s):
return s and s.strip()
list(filter(not_empty, ['A', '', 'B', None, 'C', ' ']))
# 结果: ['A', 'B', 'C']
Use filter to find prime numbers
One method of calculating prime numbers is the Ehrlich Sieve method , and its algorithm is very simple to understand:
First, list 2
all natural numbers from the beginning to construct a sequence: 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...
Take the first number of the sequence 2
, it must be a prime number, and then filter out the multiples of 2
the sequence 2
: 3, 4 , 5, 6, 7, 8 , 9, 10 , 11, 12 , 13, 14, 15, 16 , 17, 18 , 19, 20 , take the first number of the new sequence 3
, it must be a prime number, and then filter out the multiples of 3
the sequence 3
: 5, 6 , 7, 8, 9 , 10, 11, 12 , 13 , 14, 15 , 16, 17, 18 , 19, 20, ... take the first number of the new sequence 5
, and then filter out the multiples of 5
the sequence 5
: 7, 8, 9, 10 , 11, 12, 13 , 14, 15, 16, 17, 18, 19, 20 , ... Keep sifting down, and you can get all the prime numbers.
def _odd_iter(): #构造一个从3开始的奇数序列
n = 1
while True:
n = n + 2
yield n
def _not_divisible(n): #定义一个筛选函数
return lambda x: x % n > 0
def primes(): #定义一个生成器,不断返回下一个素数
yield 2
it = _odd_iter() # 初始序列
while True:
n = next(it) # 返回序列的第一个数
yield n
it = filter(_not_divisible(n), it) # 构造新序列
# 打印1000以内的素数:
for n in primes():
if n < 1000:
print(n)
else:
break
Sorted
sorted()
Function is also a higher-order function, it can also receive a key
function to achieve custom sorting, such as sorting by absolute value:
>>> sorted([36, 5, -12, 9, -21], key=abs)
[5, 9, -12, -21, 36]
To sort strings , in accordance with the size of the ASCII comparison
Suppose we use a set of tuples to represent student names and grades:
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
Use sorted()
to sort the above list by name:
L = [('Bob',75), ('Admin', 92), ('Bart', 66), ('List', 88)]
def by_name(t):
return t[0].lower()
L2 = sorted(L, key=by_name)
print(L2)
Sorting a list of tuples
Suppose we use a set of tuples to represent names and ages, and then use the sorted() function to sort the names in ascending order and age in descending order:
def sort_by_name(t):
return t[0]
def sort_by_age(t):
return t[1]
L = [('Tom', 18), ('Jerry', 15), ('Peter', 16), ('John', 20)]
list1 = sorted(L, key=sort_by_name)
list2 = sorted(L, key=sort_by_age, reverse=True)
print('sort by name asc: ', list1)
print('sort by age desc: ', list2)
Output result:
sort by name asc: [('Jerry', 15), ('John', 20), ('Peter', 16), ('Tom', 18)]
sort by age desc: [('John', 20), ('Tom', 18), ('Peter', 16), ('Jerry', 15)]
Example 4: Sorting the contents of a dictionary
There are many ways to sort a dictionary, but the core idea is the same: separate the key or value or item in the dict into a list, and then sort the list, thereby indirectly sorting the dict.
D = {'Tom': 18, 'Jerry': 15, 'Peter': 16, 'John': 20}
list1 = sorted(D.items(), key=lambda d: d[0])
list2 = sorted(D.items(), key=lambda d: d[1], reverse=True)
print('sort by key asc:', list1)
print('sort by value desc:', list2)
Output result:
sort by key asc: [('Jerry', 15), ('John', 20), ('Peter', 16), ('Tom', 18)]
sort by value desc: [('John', 20), ('Tom', 18), ('Peter', 16), ('Jerry', 15)]