Python课堂笔记-第十讲(函数)
一、高阶函数
1. 高阶函数的2个特点
高阶函数的形式可以有两种:
- 把一个函数名当作实参传给另外一个函数(“实参高阶函数”)
- 返回值中包含函数名(“返回值高阶函数”)
符合任意的一个特点,这个函数就是个高阶函数。
当我们使用一个函数名作为参数,实际上是指将指定的代码传递进了目标函数。
# 1 接收一个或多个函数作为参数
# 2 将函数作为返回值返回的也是个高阶函数
# 当我们使用一个函数作为参数的时候,实际上是将指定的代码传递到了目标函数
lst = [1,2,3,4,5,6,7,8,9,10]
a = 1
# 在函数内部定义一个函数 用来检测一个任意的偶数
def fn2(i):
if i % 2 == 0:
return True
def fn3(i):
if i > 5:
return True
return False
def fn4(i):
if i % 3 == 0:
return True
return False
# 定义一个函数
# 可以指定一个列表中的所有的偶数,保存到一个新的列表
def fn(func,l):
# 参数 l 就是被指定的列表 func
# 创建一个新的列表
new_lst = []
for n in l:
# 判断n的奇偶
if func(n):
new_lst.append(n)
return new_lst
print(fn(fn2,lst)) # 求偶数
print(fn(fn4,lst)) # 求3的倍数
# 运行结果
[2, 4, 6, 8, 10]
[3, 6, 9]
2. 常用的内置高阶函数
map()函数
map函数接收两个参数,一个是函数,一个是序列;
map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回。
格式:map(func, iter)
def func(x):
return x * x
print map(func,[1,2,3,4,5])
# 输出结果
[1,4,9,16,25]
reduce()函数
reduce把一个函数作用在一个序列上;
reduce必须接收两个参数,把结果继续和序列的下一个元素做计算。
格式:reduce(func, iter)
from functools import reduce
lt = [1, 2, 3, 4, 5]
# 求和
# s = reduce(lambda x,y: x+y, lt)
# 转换为12345
s = reduce(lambda x,y: x*10+y, lt)
print(s)
# 输出结果
12345
filter()函数
filter把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。
格式:filter(func, iter)
lt = [1, 2, 3, 4, 5]
# 提取偶数
f = filter(lambda x: x%2==0, lt)
print(list(f))
# 输出结果
2,4
sorted()函数
sorted排序后返回一个新的列表,并不改变原有变量
格式:sorted(iterable[, cmp[, key[, reverse]]])
- iterable:可迭代对象
- cmp :比较的函数,这个具有两个参数,参数的值都是从可迭代对象中取出, 此函数必须遵守的规则为,大于则返回1,小于则返回-1,等于则返回0。
- key :主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
- reverse:排序规则,reverse = True 降序 , reverse = False 升序(默认)。
# 列表排序
s1 = sorted([1,2,4,1,2,3,4,5,3,2])
print(s1)
# 指定使用排序元素的函数
d = {"a":1,"b":3,"c":2}
s2 = sorted(d.items(),key=lambda item:item[1])
print(s2)
输出结果:
[1, 1, 2, 2, 2, 3, 3, 4, 4, 5]
[('a', 1), ('c', 2), ('b', 3)]
sort 与 sorted 区别:
sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作;
sort 方法返回的是对已经存在的列表进行操作,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
二、匿名函数
匿名函数最大的好处就是,它只会用一次,用完只会就会从内存消失。
语法:lambda 参数列表 : 返回值
# 定义并调用一个匿名函数,该函数将对参数进行+1并将结果返回
result = (lambda x: x + 1)
print(result)
# 当然匿名函数也可以传递多个参数
result = (lambda x, y: x + y)
print(result)
# 不止可以对数值变量进行计算,还可以对列表进行处理,下面的代码意思相当于result = [1,2,3,4,5] * 2
result = (lambda x: x * 2)
print(result)
lambda函数表达式是专门用来创建一些简单的函数,它也是函数的另一种创建方式。
# filter() 就是一个高阶函数 它需要将别的函数作为参数来传递
# 可以将我们的可迭代对象进行一个过滤
# 返回值 可迭代的对象
# 匿名函数最大的好处就是 它只会用一次,用完只会就会从内存消失
lst = [1,2,3,4,5,6,7,8,9,10]
def fn4(i):
if i % 3 == 0:
return True
return False
# filter(fn4,lst) 等价于 filter(lambda i : i % 3 == 0,lst)
r = filter(lambda i : i % 2 != 0,lst)
print(r)
print(list(r))
# 输出结果
[1, 3, 5, 7, 9]
三、闭包
第二种形式的高阶函数,将函数作为参数返回,这种高阶函数我们称之为闭包。
闭包的好处:
- 通过闭包可以创建⼀些只有当前函数能访问的变量;
- 可以将一些私有数据藏到闭包中。
def fn():
a = 10
# 在函数内部在定义一个函数
def fn2():
print('我是fn2',a)
# 将内部函数fn2作为返回值返回
return fn2
r = fn()
r()
print(fn())
# 输出结果
我是fn2 10
<function fn.<locals>.fn2 at 0x0000017A87F8A950>
形成闭包的条件:
- 函数嵌套;
- 将内部函数作为返回值返回;
- 内部函数必须要使用到外部函数的变量。
# inner作为一个函数被outer返回,保存在一个变量foo,并且我们能够对它进行调用foo()
def outer():
x = 1
def inner():
print x # 1
return inner
foo = outer()
foo()
# 运行结果
1
从这个例子中你能够看到闭包:
- 被函数记住的封闭作用域
- 能够被用来创建自定义的函数
def outer(x):
def inner():
print(x) # 1
return inner
print1 = outer(1)
print2 = outer(2)
print1()
print2()
# 输出结果
1
2
四、装饰器
1. 装饰器的引⼊
我们可以直接通过修改函数中的代码来完成需求,但是会产生以下一些问题:
- 如果修改的函数多,修改起来会比较麻烦,不方便后期的维护;
- 这样做会违反开闭原则(ocp);
- 程序的设计,要求开放对程序的扩展,要关闭对程序的修改。
2. 装饰器的使⽤
装饰器其实就是一个闭包,把一个函数当做参数然后返回一个替代版函数。
def outer(some_func):
def inner():
print("before some_func")
ret = some_func() # 1
return ret + 1
return inner
def foo():
return 1
decorated = outer(foo) # 2
r = decorated()
print(r)
# 输出结果
before some_func
2
通过装饰器可以在不修改原来的函数的情况下对函数进行扩展,在开发中,我们都是通过装饰器来扩展函数的功能的。
# 定义一个函数 就是对其他函数进行扩展的 扩展的功能一个 是打印函数开始执行 一个是打印函数执行结束
def start_end(old):
# 内部创建了一个函数
def new_function(*args,**kwargs):
print('函数开始执行')
r = old(*args,**kwargs)
print('函数执行结束')
# 返回函数的执行结果
return r
# 返回新的函数
return new_function
# 像类似于start_end(old)这种函数我们就称之为装饰器
# 通过装饰器可以在不修改原来的函数的情况下对函数进行扩展
# 在开发中,我们都是通过装饰器来扩展函数的功能的
@start_end
def speak():
print('同学们辛苦了!!!!')
speak()
# 输出结果
函数开始执行
同学们辛苦了!!!!
函数执行结束
装饰器的原则组成:< 函数+实参高阶函数+返回值高阶函数+嵌套函数+语法糖 = 装饰器 >
参考链接:Python装饰器的通俗理解