高阶函数

 递归函数

            使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。
            针对尾递归优化的语言可以通过尾递归防止栈溢出。尾递归事实上和循环是等价的,没有循环语句的编程语言只能通过尾递归实现循环。
            python解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。
            
            普通递归函数:
                def fact(n):
                    if n == 1:
                        return 1
                    return n * fact(n-1)
            尾递归:
                def fact(n):
                    return fact_iter(n, 1)
                def fact_iter(num, product):
                    if num == 1:
                        return product
                    return fact_iter(num-1, num * product)
            尾递归调用时,如果做了优化,栈不会增长,因此,无论多少次调用也不会导致栈溢出。
            遗憾的是,大多数的编程语言都没有针对尾递归做优化,python解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出。

   

 高阶函数


        函数本身也可以赋值给变量,即:变量可以指向函数。相当于给函数区别名。
        如:a=abs
            a(-10)和abs(-10)是一样的效果。
        函数名其实就是指向函数的变量。所以可以让函数名指向别的数据。
        如:abs = 10 #将函数名abs指向了整数10,此时调用abs(-10)就会报错,因为abs不再指向绝对值函数了。
        
        既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
        编写高阶函数,就是让函数的参数能够接收别的函数。
        如:def add(x, y, func):
                return func(x) + func(y)
            调用:add(-4 , 6, abs) #10

        
        map(f, iterable):
                map函数接收两个参数,一个是函数,另一个是Iterable,map将传入的函数依次作用于序列的每个函数,并把结果作为新的Iterator返回。
                map()传入的第一个参数是f,即函数对象本身。由于结果r是一个Iterator,Iterator是惰性序列,因此可以通过list()函数让它把整个序列都计算出来并返回一个list。
                如: list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9, 0])) #将list中所有数字转化为字符:['1','2','3','4','5','6','7','8','9','0']
        
        reduce():
                reduce()函数把一个函数作用于一个序列[x1, x2, x3, x4,....]上,这个函数必须接受两个参数,reduce把结果继续和序列的下一个元素做累积计算。
                效果就是:reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
                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))
            
                或者:
                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(lamdba x, y:x*10+y, map(char2num, s))

        filter():
            和map()类似,filter()用于过滤序列,也是接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。
            filter()是一个高阶函数,关键在于正确实现一个筛选函数。filter()函数返回的是一个Iterator,也就是一个惰性序列,所以要强迫filter()完成计算结果,需要用list()函数获得所有结果并返回list。
            filter()的作用是从一个序列中筛出符合条件的元素,由于filter()使用了惰性计算,所以只有在取filter()结果的时候,才会真正筛选并每次返回下一个筛出的元素。
            
            例子:获取素数
            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)
            
            primes()也是一个无限序列,所以调用时需要设置一个退出循环的条件。
            
        
        sorted():
            sorted()也是一个高阶函数,可以接受一个list,还可以接收一个key函数来实现自定义的排序。
            key指定的函数将作用于list的每一个元素上,并根据key函数返回的结果进行排序。
            当对字符串排序时,可以将key=str.lower()忽略大小写。要进行反向排序时,不必改动key函数,可以传入第三个参数reverse = True。

                    
  返回函数

            高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。
            返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
    
  

 匿名函数

            关键字lambda表示匿名函数,冒号前面的x表示函数参数。
            匿名函数有一个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。
            用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数。
            同样,也可以把匿名函数作为返回值返回。
            如:f = lambda x:x*x
                def build(x, y):
                    return lambda: x *x +y * y
            python对匿名函数支持有限,只有一些简单的情况下可以使用匿名函数。
            

偏函数

functools.partial用于创建一个偏函数。functools.partial的作用就是把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数就会更简单。
        创建偏函数时,实际上可以接收函数对象、*args和**kw这3个参数。
        如:import functools
            int2 = functools.partial(int, base = 2)

猜你喜欢

转载自my.oschina.net/u/3767248/blog/1795775