一、高阶函数
将函数作为参数使用的函数。
func(n, funcA)
1、map()
map(function, , iterable, …) literable一个或多个序列
原意就是映射,即把集合或者列表的元素,每一个元素都按照一定规则进行操作,生成一个新的列表或者集合
map函数是系统提供的具有映射功能的函数,返回值是一个迭代对象(iterators迭代器)
示例:利用map()计算一个序列的的平方根。
>>>def square(x) : # 计算平方数
... return x ** 2
...
>>> map(square, [1,2,3,4,5]) # 计算列表各个元素的平方
[1, 4, 9, 16, 25]
>>> map(lambda x: x ** 2, [1, 2, 3, 4, 5]) # 使用 lambda 匿名函数
[1, 4, 9, 16, 25]
# 提供了两个列表,对相同位置的列表数据进行相加
>>> map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
[3, 7, 11, 15, 19]
2、reduce()
reduce(function, iterable [, initializer])
function – 函数,有两个参数
iterable – 可迭代对象
initializer – 可选,初始参数
reduce() 函数会对参数序列中元素进行累积。
函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。
- 注意事项
-函数必须有两个参数
-reduce([1,2,3,4,5]) == f( f(f(f(1,2),3), 4),5)
-reduce 需要导入functools包
>>>import functools
>>>def add(x, y) : # 两数相加
... return x + y
...
>>> reduce(add, [1,2,3,4,5]) # 计算列表和:1+2+3+4+5
15
>>> reduce(lambda x, y: x+y, [1,2,3,4,5]) # 使用 lambda 匿名函数
15
3、filter()
filter(function, iterable)
function – 判断函数,返回值是布尔值。
iterable – 可迭代对象。
过滤函数: 对一组数据进行过滤,符合条件的数据会生成一个新的列表并返回,返回类型“filter”,可用set()将结果转为集合进行打印。
- 跟map相比较:
-相同:都对列表的每一个元素逐一进行操作
-不同:
map会生成一个跟原来数据想对应的新队列
filter不一定,只要符合条件的才会进入新的数据集合
def isEven(a):
return a % 2 == 0
list = [3,4,56,3,2,3,4556,67,4,4,3,23455,43]
rst = filter(isEven, list)
print(set(rst))
利用filter(),可以完成很多有用的功能,例如,删除 None 或者空字符串:
def is_not_empty(s):
return s and len(s.strip()) > 0
filter(is_not_empty, ['test', None, '', 'str', ' ', 'END'])
结果:['test', 'str', 'END']
4、sorted()
排序算法函数
a = [234,22312,123,45,43,2,3,66723,34]
al = sorted(a, reverse=True) #对列表进行倒序排列
print(al)
a = [-43,23,45,6,-23,2,-4345]
# 按照绝对值进行排序
# abs是求绝对值的意思
# 即按照绝对值的倒序排列
al = sorted(a, key=abs, reverse=True)
print(al)
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower) #忽略大小写排序
['about', 'bob', 'Credit', 'Zoo']
二、返回函数
高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。
def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum
当我们调用lazy_sum()时,返回的并不是求和结果,而是求和函数:
>>> f = lazy_sum(1, 3, 5, 7, 9)
>>> f
<function lazy_sum.<locals>.sum at 0x101c6ed90>
调用函数f时,才真正计算求和的结果:
>>> f()
25
- 闭包(closure)
当一个函数在内部定义函数,并且内部的函数应用外部函数的参数或者局部变量,当内部函数被当做返回值的时候,相关参数和变量保存在返回的函数中,这种结构,叫闭包
返回的函数并没有立刻执行,而是直到调用了f()才执行。我们来看一个例子:
def count():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f)
return fs
f1, f2, f3 = count()
- 返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
- 出现的问题:
造成上述状况的原因是,返回函数引用了变量i, i并非立即执行,而是等到三个函数都返回的时候才统一使用,此时i已经变成了3,最终调用的时候,都返回的是 3*3
此问题描述成:返回闭包时,返回函数不能引用任何循环变量
解决方案: 再创建一个函数,用该函数的参数绑定循环变量的当前值,无论该循环变量以后如何改变,已经绑定的函数参数值不再改变
def count():
def f(j):
def g():
return j*j
return g
fs = []
for i in range(1, 4):
fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f()
return fs
三、装饰器(Decrator)
在不改动函数代码的基础上无限制扩展函数功能的一种机制,本质上讲,装饰器是一个返回函数的高阶函数
装饰器的使用: 使用@语法, 即在每次要扩展到函数定义前使用@+函数名
# 任务:
# 对hello函数进行功能扩展,每次执行hello万打印当前时间
import time
# 高阶函数,以函数作为参数
def printTime(f):
def wrapper(*args, **kwargs):
print("Time: ", time.ctime())
return f(*args, **kwargs)
return wrapper
上面代码中,内部函数要写*args, **kwargs参数,代表原传入参数不变
- 使用方法1
# 上面定义了装饰器,使用的时候需要用到@, 此符号是python的语法糖
@printTime
def hello():
print("Hello world")
hello()
- 使用方法2
# 上面对函数的装饰使用了系统定义的语法糖
# 下面开始手动执行下装饰器
# 先定义函数
def hello3():
print("我是手动执行的")
hello3()
hello3 = printTime(hello3)
hello3()
f = printTime(hello3)
f()
# 作业:
# 解释下面的执行结果
四、偏函数
- 参数固定的函数,相当于一个由特定参数的函数体
- functools.partial的作用是,把一个函数某些函数固定,返回一个新函数
def int16(x, base=16):
return int(x, base)
int16("12345")
import functools
#实现上面int16的功能
int16 = functools.partial(int, base=16)
int16("12345")