1. 匿名函数
语法: lambda [arg1 [,arg2,.......argn]]:expression 注意点: arg1:参数名,可以带多个,参数名之间都逗号隔开 expression : 表达式(数字和运算符组成的),只能有一个 匿名函数会自动将表达式的结果返回,返回的结果可以用变量来接受, 也可以直接用print()输出 调用匿名函数:变量名(参数值)
# 案例:输入任意一个数字,要求返回该数字的平方,用函数方式来实现。 # 普通函数实现 def fun1(m): # 函数名 return m * m print(fun1(2)) def fun1(m): # 函数名 return m + m print(fun1(3)) # 6 # 匿名函数实现 res = lambda m : m * m # 调用匿名函数 print(res(4)) # 匿名函数实现 add = lambda m,n : n + m # 调用匿名函数 print(add(4,10))
2. 匿名函数+内置函数的使用
max() 求最大值 min() 求最小值 sum() 求和
# 使用匿名函数求列表[10,20,30]中所有元素的和,列表中的最大值及列表中的最小值 lst = [10,20,30] print(max(lst)) print(min(lst)) print(sum(lst)) max_res = lambda x : max(x) print(max_res(lst)) min_res = lambda x : min(x) print(min_res(lst)) sum_res = lambda x : sum(x) print(sum_res(lst))
filter+匿名函数 filter(function, iterable)
# 案例:已知一个列表为[1,4,6,9,12,23,25,28,36,38,41,56,63,77,88,99],找出元素值为偶数的数据,并存放在列表当中。 lst = [1,4,6,9,12,23,25,28,36,38,41,56,63,77,88,99] # 方式一:用普通函数找出元素值为偶数的数据 new_lst = [] def isodd(m): # print(m) if m % 2 == 0: print(m) # new_lst.append(m) for i in lst: isodd(i) print(new_lst) def isodd(m): # print(m) if m % 2 == 0: return m print(list(filter(isodd, lst))) #列表:print(list(range(1,10)))
注意点:在filter的function参数,我们直接使用方法名即可,不需要括号,也不需要参数; 结果的值直接通过return返回即可 要去查看新列表的结果,一定要用list()去转换
方式二:用匿名函数来实现 print(list(filter(lambda m : m % 2 == 0, lst)))
map+匿名函数 map() 映射函数:会根据提供的函数对指定序列做映射。 语法:map(function,iterable,......) 会根据提供的括号内函数对给出的序列做一一映射 function为所指定的函数,iterable为所提供的序列,可为多个序列。
# 案例:计算列表[1,2,3,4,5]中每个元素的平方,返回新列表 lst = [1,2,3,4,5] # [1,4,9,16,25] new_lst = [] # 方式一:用普通函数实现 def fun1(m): # print(m * m) new_lst.append(m * m) for i in lst: fun1(i) print(new_lst) def fun1(m): # print(m * m) return m * m print(list(map(fun1,lst))) # 方式二:用匿名函数来实现 print(list(map(lambda m: m * m,lst)))
3.函数的传递与日志函数的使用
在python中函数名可以作为参数来传递
def fun1(): print('fun1在执行') def fun2(name): #name = fun1 print('fun2在执行') name() #函数调用的语法 #name() = fun1() fun2(fun1)
日志函数:函数中添加日志信息
# 案例1:在执行任何函数的时候,除了正常执行函数外,还有要输出下日志信息,如输入xx函数正在执行 # 解决方法:在每个函数中加上日志信息的输出 import logging def fun1(): logging.warning('fun1函数正在执行') print('fun1在执行') def fun2(name): #name = fun1 logging.warning('fun2函数正在执行') print('fun2在执行') name() #函数调用的语法 #name() = fun1() fun2(fun1) # 问题:如果其他函数也有类似的需求,怎么做? # 解决方法:将处理日志提取出来放在一个单独的函数中, # 日志处理完之后再执行真正的业务代码
日志函数:专门写一个函数来处理日志信息
def log_info(fun_name): # 函数名 logging.warning('{}函数正在执行'.format(fun_name.__name__)) fun_name() def fun1(): print('fun1在执行') def fun2(): print('fun2在执行') def info(): print('info在执行') log_info(info) log_info(fun2)
原本我要执行的info(),fun2() -->调用info(),fun2() 现在我们变成了调用log_info(info)、log_info(fun2) 问题:虽然需求实现了,但是我们调用的方法改变了? 解决方法:用装饰器来解决 -- 在不改变原来函数的代码的以及调用方式前提的前提下,去给此函数增加附属的功能
4. 装饰器的使用
定义语法: def log(func): def wrapper(*args, **kwargs): print('call %s():' % func.__name__) return func(*args, **kw) return wrapper 注意:log是装饰器的名字,自定义,要符合标识符的命名规范,以及见名知意 func:接受的一个函数名 return wrapper:装饰器的返回值是一个函数名,是装饰器里面定义的函数名 wrapper:函数名,自定义,要符合标识符的命名规范,以及见名知意,一般就是用wrapper print('call %s():' % func.__name__):装饰器添加的附属功能 return func(*args, **kw):这是装饰器传入参数函数名的调用,真正执行的函数本体 使用语法: @log def test(): pass
# 使用装饰器来解决执行函数添加日志,并且不改变调用方式的问题 import logging # 装饰器的定义 def log(func): def wrapper(): # 增加的附属功能 logging.warning('{}函数正在执行'.format(func.__name__)) # 返回执行函数本体 return func() # 返回wrapper return wrapper # 装饰器的使用 @log def fun1(): print('fun1在执行') @log def fun2(): print('fun2在执行') @log def info(name,addr): print('姓名:{},地址:{}'.format(name,addr)) # 调用 fun2() # 真正执行的是装饰器里面的wrapper() info('zs','北京') #真正执行的是装饰器里面的wrapper() # 问题:如果有些函数带参,有些函数不带参,并且带参的个数不一致的情况,装饰器好像没办法匹配
5. 装饰器的定义
执行的函数带参不一致的处理
import logging # 装饰器的定义 def log(func): def wrapper(*args,**kwargs): #*args只能接受位置参数 # 增加的附属功能 logging.warning('{}函数正在执行'.format(func.__name__)) # 返回执行函数本体 return func(*args,**kwargs) # 返回wrapper return wrapper # 装饰器的使用 @log def fun1(): print('fun1在执行') @log def fun2(name): print('fun2在执行',name) @log def info(name,addr): print('姓名:{},地址:{}'.format(name,addr)) # 调用 fun1() fun2('hhhhh') # 真正执行的是装饰器里面的wrapper() info(name='zs',addr='北京') #真正执行的是装饰器里面的wrapper()