一、匿名函数
即没有函数名的函数,又称lambda表达式。
使用关键字lambda
定义:lambda parameter_list:expression 其中parameter_list是参数列表,expression是简单表达式,不能是复杂的代码块。(x+y是表达式;a=x+y不是表达式是代码语句)
特点:1)无函数名;2)无return关键字
学习方法:对比普通函数
例:
1 #coding=utf-8 2 3 def add(x,y): 4 #普通函数 5 return x+y 6 7 f=lambda x,y:x+y#lambda表达式 8 9 print(add(1,2)) 10 print(f(1,2))
二、三元表达式
即表达式版本的if...else
例如:比较x和y,x大于y时取x,否则取y.
其他语言的三元表达式:
x>y?x:y
python语言的三元表达式:
伪代码如下
条件为真时返回的结果 if 条件判断 else 条件为假时的结果
x if x>y else y
1 #coding=utf-8 2 3 x=2 4 y=3 5 r=x if x>y else y 6 print(r)
lambda 后面非常适合三元表达式
三、map
推荐在python代码中多多使用
map是一个类,定义 map(func, *iterables),其中func是方法名,*iterables是一个或多个列表(集合)
适用场景:映射,如抛物线
例如已知列表list_x=[1,2,3,4,5,6,7,8],求list_x中各元素的平方
1、常规实现方法:
1 # coding=utf-8 2 3 def square(x): 4 return x * x 5 6 7 list_x = [1, 2, 3, 4, 5, 6, 7, 8] 8 list_y = [] 9 for x in list_x: 10 r = square(x) 11 list_y.append(r) 12 print(list_y)
2、使用map类
1)基础使用
1 # coding=utf-8 2 3 list_x = [1, 2, 3, 4, 5, 6, 7, 8] 4 r = map(lambda x: x * x, list_x) 5 # print(r) 6 print(list(r))
2)如果lambda有多个参数呢?例如求x*x+y
1 # coding=utf-8 2 3 list_x = [1, 2, 3, 4, 5, 6, 7, 8] 4 list_y = [1, 2, 3, 4, 5, 6, 7, 8] 5 6 r = map(lambda x, y: x * x + y, list_x, list_y) 7 8 print(list(r))
map(func, *iterables)中的*iterables是可变参数,支持多个列表
注意,参数顺序要正确,例如下面的代码,打印结果不同
1 # coding=utf-8 2 3 list_x = [1, 2, 3, 4, 5, 6, 7, 8] 4 list_y = [1, 1, 1, 1, 1, 1, 1, 1] 5 6 r1 = map(lambda x, y: x * x + y, list_y, list_x) 7 r2 = map(lambda x, y: x * x + y, list_x, list_y) 8 9 print(list(r1)) 10 print(list(r2))
打印结果
[2, 3, 4, 5, 6, 7, 8, 9]
[2, 5, 10, 17, 26, 37, 50, 65]
3)特殊情况,如果两个列表长度不一致,结果如何?
1 # coding=utf-8 2 3 list_x = [1, 2, 3, 4, 5, 6, 7, 8] 4 list_y = [1, 1, 1, 1] 5 6 r = map(lambda x, y: x * x + y, list_x, list_y) 7 8 print(list(r))
打印结果
[2, 5, 10, 17]
两个列表元素个数要一致,如果不一致,结果取小的。
六、reduce
1、python3中的reduce不在全局命名空间,需要import导入
from functools import reduce
2、reduce是连续计算,会对参数序列中元素进行累积。
3、reduce函数的定义:
reduce(function, sequence[, initial]) -----> value
function参数是一个有两个参数的函数,reduce依次从sequence中取一个元素,和上一次调用function的结果做参数再次调用function。 第一次调用function时,如果提供initial参数,会以sequence中的第一个元素和initial作为参数调用function,否则会以序列sequence中的前两个元素做参数调用function。
代码一:基本使用
1 #coding=utf-8 2 from functools import reduce 3 4 list_x=[1,2,3,4,5,6,7,8] 5 r=reduce(lambda x,y:x+y,list_x) 6 print(r)
36
计算过程
每一次的计算结果作为reduce中lambda的参数
(((((1+2)+3)+4)+5)+6)+7)+8=36
实现了序列求和
代码二:有初始值
1 #coding=utf-8 2 from functools import reduce 3 4 list_x=[1,2,3,4,5,6,7,8] 5 # r=reduce(lambda x,y:x+y,list_x) 6 #含初始值10 7 r=reduce(lambda x,y:x+y,list_x,10) 8 9 print(r)
运行结果
46
问题:用reduce计算旅行者坐标,起点(0,0),移动列表[(1,3),(2,-2),(-2,3)],计算旅行者的最终位置
七、filter过滤器
1、filter函数会对指定序列执行过滤操作。
2、filter函数的定义:
filter(function or None, sequence) ----> list, tuple, or string
function是一个谓词函数,接受一个参数,返回布尔值True或False。
filter函数会对序列参数sequence中的每个元素调用function函数,最后返回的结果包含调用结果为True的元素。
返回值的类型和参数sequence的类型相同
3、代码示例一
1 #coding=utf-8 2 3 '''过滤掉列表中的0''' 4 list_x=[1,0,2,0,3,0,4,0] 5 6 #lambda必须返回一个可以判断真假的结果,r中的返回True或False 7 r=filter(lambda x:True if x!=0 else False,list_x) 8 #r1中的lambda返回非0 9 r1=filter(lambda x:x,list_x) 10 print(list(r)) 11 print(list(r1))
代码示例二
#coding=utf-8 '''过滤掉列表中小写字母''' list_n=['a','B','C','f','e'] r=filter(lambda x:True if x.isupper() else False,list_n) print(list(r))
"C:Program FilesPython36python3.exe" E:/pyClass/eleven/c16.py ['B', 'C']
八、命令式编程VS函数式编程
命令式编程即过程控制,主要关键字:def if ..else for
函数式编程,必须关键字:三个类map reduce filter,一个表达式lambda
lambda是函数式编程的最基本单元
lisp语言是函数式编程的鼻祖
python支持函数式编程,但本质还是命令式编程,适当使用可使代码简洁。
九、装饰器一
很有用,并非python独有,如java中的注释。
1、什么是装饰器
2、适用场景
3、能解决什么问题
1 #coding=utf-8 2 3 '''1)原有函数f1,实现打印功能''' 4 # def f1(): 5 # print("this is a function") 6 7 8 ''' 9 2)新需求:现在要在f1中增加打印时间戳的功能 10 ''' 11 import time 12 # 13 # def f1(): 14 # print(time.time()) 15 # print("this is a function") 16 # 17 # #调用 18 # f1() 19 20 ''' 21 3)新需求:有多个函数,要求在每个函数中增加打印时间戳的功能 22 原则:开闭原则告诉我们要对扩展开发,对修改关闭; 23 尽量不修改原有函数的定义和实现,而是通过扩展实现新的需求 24 ''' 25 #定义一个打印时间戳的函数 26 def f1(): 27 print("this is a function f1") 28 29 def f2(): 30 print("this is a function f2") 31 32 def print_current_time(func): 33 print(time.time()) 34 func() 35 36 print_current_time(f1) 37 print_current_time(f2)
运行结果
"C:Program FilesPython36python3.exe" E:/pyClass/eleven/c17.py 1532585365.6654336 this is a function f1 1532585365.6654336 this is a function f2
以上代码虽然满足需求:没有修改原来的函数,实现了新需求,但是只是在每个函数之前增加了一句打印时间戳的语句,并没有提醒和原有函数的关联性,其本质和下面的代码没有区别。
1 print(time.time()) 2 f1() 3 print(time.time()) 4 f2()
十、装饰器二
1 #coding=utf-8 2 3 import time 4 5 ''' 6 使用闭包,定义一个装饰器(decorator),内部嵌套被封装(wrapper)函数 7 def decorator(): 8 9 def wrapper(): 10 pass 11 return wrapper 12 ''' 13 def f1(): 14 print("this is a function f1") 15 16 #定义装饰器 17 def decorator(func): 18 def wrapper(): 19 print(time.time()) 20 func() 21 return wrapper 22 23 #调用 24 f=decorator(f1) 25 f()
十一、装饰器三
上面的代码,定义复杂,调用也复杂。我们可以接受定义复杂,但不能接受调用复杂。那有没有什么方式可以不用改变调用方式,来实现呢?
就是使用语法糖,关键字@
1 #coding=utf-8 2 import time 3 4 #定义装饰器 5 def decorator(func): 6 def wrapper(): 7 print(time.time()) 8 func() 9 return wrapper 10 11 #使用语法糖 12 @decorator 13 def f1(): 14 print("this is a function f1") 15 16 #原有调用方式不变 17 f1()
运行结果
"C:Program FilesPython36python3.exe" E:/pyClass/eleven/19.py 1532586681.7921555 this is a function f1
十二、装饰器四
上面讲的被装饰的函数是不带参数的,如果f1()带参数呢?
解决方式很简单,只要在定义装饰器的内部函数wrapper()中增加参数即可,调用方式不变
代码如下:
1 #coding=utf-8 2 import time 3 4 #定义装饰器 5 def decorator(func): 6 def wrapper(func_name): 7 print(time.time()) 8 func(func_name) 9 return wrapper 10 11 #使用语法糖 12 @decorator 13 def f1(func_name): 14 print("this is a function "+func_name) 15 16 #原有调用方式不变 17 f1('f1')
打印结果
"C:Program FilesPython36python3.exe" E:/pyClass/eleven/c20.py 1532587192.487322 this is a function f1
进一步,如果被装饰的函数有多个,且每个函数的参数个数也不同,如f1()有一个参数,f2()有两个参数,f3()有三个参数。。。该如何实现?
装饰器需要具有通用性,任何类型的函数都可以使用,那么可变参数可以解决这个问题。
代码如下:
1 #coding=utf-8 2 import time 3 4 #定义装饰器 5 def decorator(func): 6 def wrapper(*args): 7 print(time.time()) 8 func(*args) 9 return wrapper 10 11 #使用语法糖 12 @decorator 13 def f1(a): 14 print("this is a function "+a) 15 16 #使用语法糖 17 @decorator 18 def f2(a,b): 19 res=a+b 20 print(res) 21 22 23 #原有调用方式不变 24 f1('python') 25 print(f2(1,3))
十三、装饰器五
如果f3()中含有关键字参数呢?
1 def f3(a,b,**kw): 2 print(a) 3 print(b) 4 print(kw)
在内层函数wrapper()中增加**kw参数
代码实现如下
#coding=utf-8 import time #定义装饰器 def decorator(func): def wrapper(*args,**kw): print(time.time()) func(*args,**kw) return wrapper #使用语法糖 @decorator def f1(a): print("this is a function "+a) #使用语法糖 @decorator def f2(a,b): print(a) print(b) @decorator def f3(a,b,**kw): print(a) print(b) print(kw) #原有调用方式不变 f3('test1','test2',x=1,y=2,z=3)
运行结果
"C:Program FilesPython36python3.exe" E:/pyClass/eleven/c20.py
1532588529.5278778
test1
test2
{'x': 1, 'y': 2, 'z': 3}
小tips:func(*args,**kw)通杀所有函数
十四、装饰器六
1、解决什么问题:
装饰器实际上就是为了给某程序增添功能,但又不修改源代码,满足以下三个条件:
1)不能修改被装饰的函数的源代码
2)不能修改被装饰的函数的调用方式
3)满足1)2)的情况下给程序增添功能
2、适用场景
- 1.可以在外层函数加上时间计算函数,计算函数运行时间;
- 2.计算函数运行次数;
- 3.可以用在框架的路由传参上;
- 4.插入日志,作为函数的运行日志;
- 5.事务处理,可以让函数实现事务的一致性,让函数要么一起运行成功,要么一起运行失败;
- 6.缓存,实现缓存处理;
- 7.权限的校验,在函数外层套上权限校验的代码,实现权限校验;