【python】匿名函数与装饰器

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()

 

上一篇:Python之hasattr,getattr与setattr的使用


下一篇:OpenCV-Python教程:图像加减乘除运算的共性问题