注:此为慕课网Python(不打广告)视频的观看笔记,只做记录之用,并未勘误。
匿名函数
特点:
定义函数时不需要定义函数名
实现:
借助 lambda 关键字
lambda parameter_list: expression
注意:expression只能包含表达式!不能包含语句!
示例:
一般函数:
def add(x, y):
return x + y
上述add函数的匿名形式:(匿名函数 或 叫做Lambda表达式)
lambda x,y: x+y
匿名函数的调用:
因为没有名字,所以需要赋值给变量,然后调用
f = lambda x,y: x+y
print(f(1,2)) #输出 3
三元表达式
地位:
表达式版本的if else 语句
实现:
Java的形式 x > y ? 1 : 1
Python的三元表达式
[条件为真时返回的结果] if [条件判断] else [条件为假时的返回结果]
示例:
x = 1
y = 2
print( True if x > y else False) #输出 False
class map(func,*iterables)
使用场景
对序列中的全部元素执行相同的操作
应用:
求列表中每个数字的平方
示例:
list_x = [1,2,3,4,5,6]
def func(x):
return x * x
print(map(func, list_x))
#输出 <map object at 0x0000000000A5D7F0>
print(list(map(func, list_x)))
#输出 [1, 4, 9, 16, 25, 36]
注意:
map会吧集合中的每个元素都传入到第一个参数,func中去
即按照一定的规则,对一族元素进行映射,规则就是func中的逻辑
map+lambda:
注意:
map(func,*iterables)结合Lambda表达式
直接替换掉参数func
注意第二个参数 *iterables,带星号,表示可变参数
如果func参数有多个,第二个参数位置可以传入多个list
示例:
完成返回平方的功能:
print( list( map( lambda x: x*x, [1,2,3,4,5] ) ) )
#输出 [1, 4, 9, 16, 25]
Lambda表达式有两个参数
print( list( map( lambda x,y: x*y, [1,2,3,4,5],[1,2,3,4,5] ) ) )
#输出[1, 4, 9, 16, 25]
注意多个参数时会一一对照,多余会丢弃
print( list( map( lambda x,y: x*y, [1,2,3,4,5],[1] ) ) )
#输出[1]
上述输出只有一个元素,因为输入的两个参数只有第一个元素满足运行条件
def reduce
注意:
map类在全局命名空间,不需要引入模块,reduce函数需要引入functools
def reduce(function,sequence,initial=None)
示例:
from functools import reduce
list_x = [1,2,3,4]
#完成求和
print( reduce( lambda x,y:x+y, list_x ) )
#输出 10 运算过程:
#1 2 3 4 ...
# 3 3 4 ...
# 6 4 ...
# 10...
应用场景:
连续规约计算,从前向后对数据进行两两规约计算
带initial参数:
print( reduce( lambda x,y:x+y, list_x, 10 ) )
#输出 10 运算过程:
#10 1 2 3 4 ...
# 11 2 3 4 ...
# 13 3 4 ...
# 16 4 ...
# 20
扩展:
map/reduce 映射+规约,进行并行计算(大数据处理)
<< 更多精彩尽在『程序萌部落』>>
<< https://www.cxmoe.com >>
class filter(func or None, iterables)
注意:
由参数可知,只能对一个序列进行处理,参数func仍然可以被Lambda表达式替换
另:第一个参数必须可以返回True/False 或者代表True/False的值
filter依靠TF来判断是否要剔除,返回false表示保留
示例:
print( filter( lambda x:False if x == 0 else True, [0,0,1,2,3,0] ))
#输出 <filter object at 0x000000000111D828>
print( list( filter( lambda x:False if x == 0 else True, [0,0,1,2,3,0] )))
#输出 [1, 2, 3]
对比:
命令式编程:依靠def,if else,for/while等等
函数式编程:依靠map,reduce,filter + Lambda(三大函数 + 算子)
解释:
map,reduce近似循环
filter近似判断
Lambda近似函数
上述集合使用,可以完成流程控制
注意:
Python只是支持部分函数式编程的特性,本身并不是函数式编程语言
装饰器
地位:
非常有用、常用,是一种设计模式,类似Java的注解
示例:
对所有函数追加打印当前时间的功能
代码:
import time
def func1():
print(time.time())
#输出 1509550613.9346058 Unix时间戳
print('This is a function')
func1()
追加修改原则:
开闭原则:对修改是封闭的,对扩展是开放的,如果需要打印时间,会迫使修改函数内部
进一步:
使用函数式编程思想的封装,没有违反开闭原则
def func2():
print('This is a function')
def print_time(func):
print(time.time())
func()
print_time(func2)
上述缺点:打印时间并没有和原函数绑定
再进一步:
使用装饰器完成上述功能
装饰器的基本结构:
def decorator():
def wrapper():
pass#装饰器的逻辑
return wrapper
示例:
import time
def func1():
print('This is a function')
#构造装饰器
def decorator(func):
def wrapper():
print(time.time())
func()
return wrapper
decorator(func1)() 完成调用
解释:
真正业务逻辑在wrapper内
缺点:
仍然没有将打印时间和原始函数绑定起来
再进一步:
使用装饰器语法糖,使用@符号
代码:
import time
#构造装饰器
def decorator(func):
def wrapper():
print(time.time())
func()
return wrapper
@decorator
def func1():
print('This is a function')
func1() #完成调用,而且没有改变原有调用逻辑
评价:
这才是完整的有意义的装饰器的使用方法,只需要在原有函数定义上添加
@decorator就会执行附加操作,体现了AOP面向切面编程
对带参数的原函数添加装饰器
示例:
import time
#构造装饰器
def decorator(funcname):
def wrapper(*fc):
#此处的参数,应该和被修饰函数的参数个数相对于,
#但是为了通用性,应该使用*params可变参数形式
print(time.time())
funcname(*fc)
return wrapper
@decorator
def func1(f_param):
print('This is ',f_param)
@decorator
def func2(param1,param2):
print('This is ',param1,param2)
func1('Tom')
func2('Tom','Jack')
上述成功完成了对不同参数的函数进行添加装饰器
进一步优化
适应关键字参数:
import time
#构造装饰器
def decorator(funcname):
def wrapper(*fc,**kw): #参数**kw适用于关键字参数
print(time.time())
funcname(*fc,**kw)
return wrapper
@decorator
def func2(param1,**param2):
print('This is ',param1,param2)
func2('Tom',a = '1',b = '2') #正确适应了关键字参数的函数
关键字参数,回顾:
对于含有关键字参数的函数
def func2(param1,**param2):
print('This is ',param1,param2)
func2('Tom',a = '1',b = '2')
输出 This is Tom {'b': '2', 'a': '1'}
综上:
此时的装饰器:
def decorator(funcname):
def wrapper(*fc,**kw):
print(time.time())
funcname(*fc,**kw)
return wrapper
在待装饰函数具有多个可变参数,或者包含关键字参数的情况均可使用
装饰器小结:
装饰器的思想:对封装的单元追加行为,保证原有单元的稳定性,
不破坏单元内的代码,遵循开闭原则,更加体现了装饰器内代码的复用
应用场景:
flask内,添加@api.route可以使函数变为控制器
@api.route('/get',methods=['GET'])
def test_http():
p = request.agrs.get('name')
return p,200
添加多个装饰器,追加不同的操作
@api.route('/get',methods=['GET'])
@auth.login_required
def get_money():
p = request.agrs.get('psw')
r = generate_hash(p)
return 'user',200
😒 留下您对该文章的评价 😄