Python支持高阶函数(Higher-order function)

    什么是高阶函数呢?把函数作为参数传入,这样的函数称为高阶函数。

    高阶函数的特点:
    1、变量可以指向函数

    这个例子告诉我们:是函数,abs(10)是函数调用;可以将函数赋给一个变量,这个变量也指向了函数。

    2、函数名也是变量

    1. >>> abs = 10
    2. >>> abs
    3. 10

    例子中,当我们把一个函数名重新赋值后,该函数名不再指向函数,而是指向整数10,说明函数名本身也是变量,是指向函数的变量。

    3、函数参数可以传入函数

    1. def test(x,y,f):
    2. return f(x) + f(y)
    3. print(test(1, -2, abs))

    输出:

    1. 3
    1. map(function f, Iterable iterable)
    2. # 返回: Iterable

    map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。

    示例:

    1. def f(x):
    2. return x*x
    3. iterator = map(f, [1,2,3,4])
    4. print(list(iterator))

    输出:

    1. [1, 4, 9, 16]
    1. iterator = map(f, [1,2,3,4])
    2. for x in iterator:
    3. print(x)

    输出:

    1. 1
    2. 4
    3. 9

    reduce()函数同样接收两个参数,一个是函数,一个是Iterable,reduce把结果继续和序列的下一个元素做累积计算,返回的是累计结果,非迭代器。注意的是reduce()传入的函数 函数f 必须接收两个参数。

    1. import functools
    2. def f(x,y):
    3. return x*10+y
    4. print(iterator)

    输出:

    1. 1234

    reduce在Python3.3+已经移到functools里了,需要先导入functools。

    字符串转整数示例:

    1. from functools import reduce
    2. def str2int(s):
    3. def fn(x, y):
    4. return x * 10 + y
    5. def char2num(s):
    6. return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
    7. return reduce(fn, map(char2num, s))

    调用:

    1. >>> str2int('135')
    2. 135

    reduce()还可以接收第3个可选参数,作为计算的初始值。如果把初始值设为100,计算:

    1. def f(x, y):
    2. return x + y
    3. reduce(f, [1, 3, 5, 7, 9], 100)

    结果将变为125。

    1. filter(function f, Iterable iterable)
    2. # 返回: Iterable

    map()类似,filter()也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。True保留,False丢弃。

    1. def f(x):
    2. if x % 2 == 0:
    3. return True
    4. r = filter(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
    5. print(list(r))

    输出:

    1. [2, 4, 6, 8]

    Python内置的sorted()函数就可以对list进行排序,按从小到大。

    1. s = sorted(l)
    2. print(s)

    输出:

    1. [2, 5, 7, 10]
    1. def opposite(x):
    2. return -x
    3. l = [10,5,2,7]
    4. print(s)

    输出:

    1. [10, 7, 5, 2]

    装饰器(Decorator)是一种在代码运行期间动态增加功能的方式。例如,我们有个写日志的函数log(),我们希望在不修改该函数的情况取增强该函数的功能,比如日志前打印一行时间和该函数名:

    1. import time
    2. def writelog(func):
    3. def wrapper(*args, **kw):
    4. print('['+ time.strftime('%Y-%m-%d %H:%M:%S') + '] :' + func.__name__)
    5. return func(*args, **kw)
    6. return wrapper
    7. @writelog
    8. def log(msg):
    9. print(msg)
    10. log('This is a test msg.')

    输出:

    1. [2017-01-11 21:10:53] :log
    2. This is a test msg.

    这个例子里我们编写了装饰器writelog()用来增加函数log()的功能,只需要在函数log()前加@writelog即可。其中func.__name__代表函数的函数名。内部函数wrapper()名字非固定的,可以自定义名称。

    wrapper()函数的参数定义是(*args, **kw),因此,wrapper()函数可以接受任意参数的调用。

    大家不要被这个名字给吓到,其实很简单的一个东西:用于固定函数的行为。例如,函数int(x, base=10)默认只需要传第一个参数,因为第二个参数默认是10,代表10进制。

    如果我们想默认使用2进制呢,一般是这样:

    1. def int2(x):
    2. return int(x, 2)

    而偏函数就是专门干这事情的。使用偏函数表示上面自定义方法就是:

    1. import functools
    2. int2 = functools.partial(int, base=2)
    3. print(int('10'))

    输出:

    是不是很简单?