7.1 匿名函数lambda表达式
匿名函数,就是没有名字的函数,在程序中不用使用def进行定义,可以直接使用lambda关键字编写简单的代码逻辑。lambda本质上是一个函数对象,可以将其赋值给另一个变量,再由该变量来调用函数,也可以直接使用。
- lambda表达式的基本格式
lambda 入参 : 表达式
一般定义的函数
def power(x):
return x ** 2
print(power(2))
改写成匿名函数
power = lambda x : x ** 2
print(power(2))
或
print((lambda x: 2 * x)(8))
多个入参
power = lambda x, n: x ** n
print(power(2, 3))
- lambda表达式的使用场景
一般适用于创建一些临时性的,小巧的函数。比如上面的 power函数,我们当然可以使用 def
来定义,但使用 lambda 来创建会显得很简洁,尤其是在高阶函数的使用中。
定义一个函数,传入一个list,将list每个元素的值加1
def add(l = []):
return [x +1 for x in l]
print(add([1,2,3]))
改成加1,加2
def add(func,l = []):
return [func(x) for x in l]
print(add(lambda x:x+1,[1,2,3]))
print(add(lambda x:x+2,[1,2,3]))
7.2 map
- map的基本格式
map(func, *iterables)
map()函数接收两个以上的参数,开头一个是函数,剩下的是序列,将传入的函数依次作用到序列
的每个元素,并把结果作为新的序列返回。也就是类似map(func,[1,2,3])
将list的每个元素值加1
def add(x):
return x + 1
result = map(add, [1, 2, 3, 4])
print(type(result))
print(list(result))
使用lambda
result = map(lambda x: x + 1, [1, 2, 3, 4])
print(type(result))
print(list(result))
如果有两个序列且个数不一样,结果以个数少的为准
print(list(map(lambda x, y: x + y, [1, 2, 3], [4, 5])))
输出:
[5,7]
7.3 reduce
reduce函数的基本格式
reduce(function, sequence, initial=None)
reduce把一个函数作用在一个序列上,这个函数必须接收两个参数,reduce函数把结果继续和序列的下一个元素做累积计算,跟递归有点类似,reduce函数会被上一个计算结果应用到本次计算中
使用reduce函数,计算一个列表的乘积
from functools import reduce
def func(x, y):
return x * y
print(reduce(func, [1, 2, 3, 4]))
结合lambda
from functools import reduce
print(reduce(lambda x, y: x * y, [1, 2, 3, 4]))
7.4 filter
filter函数的基本格式
filter(function_or_None, iterable)
filter()接收一个函数和一个序列。把传入的函数依次作用于每个元素,然后根据返回值是
True还是False决定保留还是丢弃该元素。
使用filter函数对给定序列进行操作,最后返回序列中所有偶数
print(list(filter(lambda x: x % 2 == 0, [1, 2, 3, 4, 5])))
7.5 sorted
sorted 可以对所有可迭代的对象进行排序操作
sorted的基本格式
sorted(iterable, key=None, reverse=False)
- iterable – 可迭代对象。
- key – 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中指定可迭代对象中的一个元素来进行排序。
- reverse – 排序规则,reverse = True 降序 , reverse = False 升序(默认)。
对序列做升序排序
print(sorted([1, 6, 4, 5, 9]))
对序列做降序排序
print(sorted([1, 6, 4, 5, 9], reverse=True))
对存储多个列表的列表做排序
data = [["Python", 99], ["c", 88]]
print(sorted(data, key=lambda item: item[1]))
7.6 闭包
def my_power():
n = 2
def power(x):
return x ** n
return power
p = my_power()
print(p.__closure__)
输出:
(<cell at 0x0000020347A99B58: int object at 0x00007FFA3A52A1B0>,)
是闭包
closure是内部函数的一个属性,用来保存环境变量
n = 2
def my_power():
def power(x):
return x ** n
return power
n = 3
p = my_power()
print(p.__closure__)
输出:
None
不是闭包
7.7 闭包问题
下面的程序是否是闭包,能否正常运行
def my_power():
n = 2
def power(x):
nonlocal n
n += 1
return x ** n
return power
p = my_power()
print(p(3))
输出:
UnboundLocalError: local variable ‘n’ referenced before assignment
由上可知,不是闭包
改为
def my_power():
n = 2
def power(x):
nonlocal n
n += 1
return x ** n
return power
p = my_power()
print(p(3))
nonlocal关键字用来在函数或其他作用域中使用外层(非全局)变量
def my_power():
n = 2
L = []
for i in range(1, 3):
def power():
return i ** n
L.append(power)
return L
f1, f2 = my_power()
print(f1())
print(f2())
print(f1.__closure__[0].cell_contents)
print(f2.__closure__[0].cell_contents)
输出:
4
4
2
2
python的函数只有在执行时,才会去找函数体里的变量的值,如果形参不确定,python只会记住最后一个值。
改成
def my_power():
n = 2
L = []
for i in range(1, 3):
def power(i):
return i ** n
L.append(power(i))
return L
f1, f2 = my_power()
print(f1)
print(f2)
7.8 装饰器及其应用
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结
构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提
供了额外的功能。
如
延时4秒
import time
start = time.time()
time.sleep(4)
end = time.time()
print(end - start)
延时2秒输出“Hello World”
import time
def my_fun():
begin = time.time()
time.sleep(2)
print("Hello World")
end = time.time()
print(end-begin)
my_fun()
若不改变原有函数
import time
def my_fun():
print("Hello Wold")
def my_time(func):
begin = time.time()
time.sleep(2)
func()
end = time.time()
print(end - begin)
my_time(my_fun)
这种方式,因为要增加功能,导致所有的业务调用方都得进行修改,此法明显不可取。
另一种方式
import time
def print_cost(func):
def wrapper():
begin = time.time()
time.sleep(2)
func()
end = time.time()
print(end - begin)
return wrapper
@print_cost
def my_fun():
print("这里一个函数")
my_fun()
第二种方式并没有修改func函数的内部实现,而是使用装饰器模式对其功能进行装饰增强