递归函数
使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。
针对尾递归优化的语言可以通过尾递归防止栈溢出。尾递归事实上和循环是等价的,没有循环语句的编程语言只能通过尾递归实现循环。 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) #10map(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']
例如,对于list [1, 2, 3, 4, 5, 6, 7, 8, 9]
如果希望把list的每个元素都作平方,就可以用map()函数:
因此,我们只需要传入函数f(x)=x*x,就可以利用map()函数完成这个计算:
def f(x): return x*xprint(map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
输出结果:
[1, 4, 9, 10, 25, 36, 49, 64, 81]
注意:map()函数不改变原有的 list,而是返回一个新的 list。
利用map()函数,可以把一个 list 转换为另一个 list,只需要传入转换函数。
由于list包含的元素可以是任何类型,因此,map() 不仅仅可以处理只包含数值的 list,事实上它可以处理包含任意类型的 list,只要传入的函数f可以处理这种数据类型。
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)