函数式编程

高阶函数

传入函数

既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数称为高阶函数

def add(x, y, f):
    return f(x) + f(y)
print(add(-3,5,abs))

map/reduce

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.
map()接收两个参数,一个是函数,一个是Iterbale,map将传入的函数依次作用于序列的每个元素,并把结果作为新的Iterator返回

def f(x):
    return x * x
r = map(f, [1,2,3,4,5])
list(r)

把list所有数字转为字符串

list(map(str, [1,2,3,4,5]))

reduce

reduce(function, sequence[, initial]) -> value
Apply a function of two arguments cumulatively to the items of a sequence,from left to right, so as to reduce the sequence to a single value.For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates ((((1+2)+3)+4)+5). If initial is present, it is placed before the items of the sequence in the calculation, and serves as a default when the sequence is empty.

reduce()接收两个参数,函数和序列,其中函数也要有两个参数,reduce把结果和序列剩下的部分依次进行计算,效果就是

reduce(f,[x1,x2,x3,x4,x5])=f(f(f(f(x1,x2),x3),x4),x5)

如求和

from functools import reduce
def add(x,y):
    return x+y
reduce(add,[1,2,3,4,5])

把序列变换成整数

from functools import reduce
def fn(x,y):
    return x * 10 + y
reduce(fn,[1,2,3,4,5])

把str转换成int

from functools import reduce
def fn(x,y):
    return x * 10 + y
def chr2num(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(chr2num,'12345'))

整理成str2int的函数

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 chr2num(s):
        return DIGITS[s]
    return reduce(fn, map(chr2num, s))

用lambda函数精简

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 chr2num(s):
    return DIGITS[s]
def str2int(s):
    return reduce(lambda x, y: x * 10 + y, map(chr2num, s))

filter

python内建的filter()函数用于筛选序列,接收一个函数和序列作为参数,与map()不同的是,把传入的函数依次作用于元素,并根据返回值是True还是False来确定是保留还是去除该元素
如在一个list中,删掉偶数,只保留奇数

def is_odd(n):
    return n%2==1
list(filter(is_odd, [1,2,3,4,5]))

把一个序列中的空字符串删掉

def not_empty(s):
    return s and s.strip()
list(filter(not_empty, ['a','','b',None,'c',' ']))

用filter求素数

计算素数的一个方法是埃氏筛法,首先构造从2开始的所有自然数序列,取序列的第一个数2,它是素数,然后用2把2的倍数筛掉;取序列的第一个数3,它是素数,然后用3把序列的3的倍数筛掉;取新序列的第一个数5,然后用5把序列的5的倍数筛掉;不断筛下去,就可以得到所有的素数

def _odd_iter():
    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)
for n in primes():
    if n < 1000:
        print(n)
    else:
        break

sorted

sorted([36,5,-12,9,-21], key=abs)

key指定的函数将作用于list的每一个元素上,并根据key函数返回的结果进行排序

sorted(['bob','about','Zoo','Credit'],key=str.lower)

对列表按名字排序

L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
def by_name(t):
    for s in t:
        return s.lower()
L2 = sorted(L, key=by_name)
print(L2)

按成绩从高到低排序

def by_score(t):
    for n in t:
        if isinstance(n, str):
            pass
        else:
            return n
L3 = sorted(L, key=by_score, reverse=True)
print(L3)

返回函数

函数作为返回值

def calc_sum(*args):
    ax = 0
    for n in args:
        ax += n
    return ax
def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax += n
        return ax
    return sum

当调用lazy_sum(),返回的是求和函数

f = lazy_sum(1,2,3,4,5)

调用函数f(),才得到求和结果

f()
当调用lazy_sum(),即使每次传入参数一样,也会返回新的函数

闭包

def count():
    fs = []
    for i in range(1,4):
        def f():
            return i*i
        fs.append(f)
    return fs

f1, f2, f3 = count()

执行

f1()
f2()
f3()

得到相同结果9,原因在于返回的函数引用了变量i,但它并非立即执行,等到3个函数都返回时,i已经变成3,因此最终结果为9
返回闭包时牢记,返回函数不要引用任何循环变量,或许后续会发生变化的变量
如果一定要引用循环变量,方法是再创建一个函数,用该函数的参数绑定循环变量的当前值

def count():
    def f(j):
        def g():
            return j*j
        return g
    fs = []
    for i in range(1,4):
        fs.append(f(i))
    return fs

f1, f2, f3 = count()
f1()#1
f2()#4
f3()#9

利用闭包返回一个计数器函数,每次调用返回递增整数

#列表
def createCounter():
    count = []
    def counter():
        count[0] = count[0] + 1
        return count[0]
    return counter
#生成器
def createCounter():
    g = (i for i in range(1, 1000))
    def counter():
        return next(g)
    return counter
#用nonlocal,LEGB原则,nonlocal是python3引入的,只能用于嵌套函数中,在嵌套函数中使用nonlocal声明变量,可以修改外层函数中的变量
def createCounter():
    n = 0 
    def counter():
        nonlocal n
        n = n + 1
        return n
    return counter

匿名函数

匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数,也可以将匿名函数作为返回值返回

装饰器

待补充

偏函数

待补充

posted @ 2020-03-04 11:04  WayneWW  阅读(168)  评论(2)    收藏  举报