高阶函数&匿名函数&闭包&装饰器

1.高阶函数(闭包)

  • 接收函数作为参数,或者将函数作为返回值的函数都是高阶函数
# 定义一个函数,将列表中所有的偶数,保存到一个新的列表返回

lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

def fn(lst):
    # 创建一个新的列表
    new_lst = []
    # 对列表进行遍历
    for i in lst:
        # 判断奇偶
        # if not i & 1:
        if i % 2 ==0:
            new_lst.append(i)
    return new_lst

上述的代码将判断奇偶的函数直接嵌套进了fn函数中,若要输出大于5的数时,就需要对fn函数再进行修改,不太方便。因此可以采用高阶函数,如下:

# fn2()函数是判断偶数的函数
def fn2(n):
    if n % 2 == 0:
        return True

# fn3()函数是判断大于5的数的函数
def fn3(n):
    if n >5:
        return True
    else:
        return False

# 该函数即为高阶函数(参数一:作为返回值的函数对象  参数二)
def fn(func,lst):
    # 创建一个新的列表
    new_lst = []
    # 对列表进行遍历
    for i in lst:
        if func(i):
            new_lst.append(i)
    return new_lst
    
print(fn(fn2,lst))  # 注意这里应该用fn2,而不是fn2(),因为需要传入的是对象,而非调用该函数

2. 闭包

  • 将函数作为返回值也是高阶函数我们也称为闭包
  • • 闭包的好处
    • 通过闭包可以创建一些只有当前函数能访问的变量
    • 可以将一些私有数据藏到闭包中
  • 行成闭包的条件
    • 函数嵌套
    • 将内部函数作为返回值返回
    • 内部函数必须要使用到外部函数的变量

例1:

def fn():
    a = 123
    # 函数内部定义了一个函数
    def fn1():
        print('我是fn1...',a)

    # 将函数fn1作为返回值返回
    return fn1

# r这个函数总是能访问fn()内部的变量
r = fn()  # r接收的是fn的返回值:fn1这个对象,即r=fn1
r()  # 相当于执行fn1()函数,打印  我是fn1...',123
print(r)  # <function fn.<locals>.fn1 at 0x0000022D26392950>
print(a)  # 访问不到a
print(fn())  # 返回的是函数对象fn1 <function fn.<locals>.fn1 at 0x0000022D263929D8>

例2:定义一个函数 求平均值

# 定义一个函数  求平均值
nums = []
def average(n):
    # 将n添加到列表当中
    nums.append(n)
    return sum(nums) / len(nums)
print(average(10))  # 10.0
print(average(30))  # 20.0
print(average(10))  # 16.666666666666668

# 若是中间将nums清空,会影响平均值
print(average(10))
print(average(30))
nums = []      # 这个会影响下面的值,会清空nums的值
print(average(10))  # 10.0

面对上面那种影响情况,可以采用闭包来解决

# 但是下面的闭包方法,nums=[]就不会影响后面的值
def make_average():
    nums = []
    def average(n):   #  函数嵌套
        # 将n添加到列表当中
        nums.append(n)  # 内部函数用到了外部函数的变量nums
        return sum(nums)/len(nums)
    return average   # 将内部函数作为返回值
average = make_average()
print(average(10))   # 10
nums = []    # 即不会清空,不起作用,不会影响函数内部的nums
print(average(30))   # 20 

3.匿名函数

  • 1.filter() 可以从序列中过滤出符合条件的元素,保存到一个新的序列中
    • 参数一 函数 根据该函数来过滤序列
    • 参数二 需要过滤的序列
    • 返回值 过滤后的新序列
      例3:filter 过滤函数 求3的倍数
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 3的倍数
def fn3(n):
    if n % 3 == 0:
        return True
    return False

print(list(filter(fn3,lst)))  # [3, 6, 9]
print(filter(fn3,lst))   # <filter object at 0x00000243A7101BE0>
  • 2.lambda 函数:该函数表达式专门用来创建一些 简单的 函数,它是函数的另一种创建方式
    • 语法: lambda 参数列表 : 返回值

例4:lambda 函数 一个简单函数:求两数之和

def fn5(a,b):
    return a+b
# fn5()函数与下面的lambda函数等价
(lambda a,b : a + b)(1,2)  # 匿名函数,不需要重新定义一个函数,大材小用
print(fn5(1,2))   # 3
print((lambda a,b : a + b)(1,2))  # 3

4.装饰器的引入与使用

4.1 装饰器的引入

  • 我们可以直接通过修改函数中的代码来完成需求,但是会产生以下一些问题
    • 如果修改的函数多,修改起来会比较麻烦
    • 不方便后期的维护
    • 这样做会违反开闭原则(ocp):程序的设计,要求开发对程序的扩展,要关闭对程序的修改
# 求和函数
def add(a,b):
    r = a + b
    return r
# 求乘积函数
def mul(a,b):
    return a * b
# 我们希望在不修改原函数的情况下,对函数进行扩展
# 可以定义一个新的函数,来对函数进行扩展

#  对加法进行扩展
def new_add(a,b):
    print('函数开始执行....')
    r = add(a,b)
    print('函数执行结束....')
    return r
q = new_add(1,2)
print(q) 
# 结果 : 
# 函数开始执行....
# 函数执行结束....
# 3

# 对乘法进行扩展
def new_mul(a,b):
    print('函数开始执行....')
    r = mul(a,b)
    print('函数执行结束....')
    return r
q = new_mul(1,2)
print(q)
# 结果 : 
# 函数开始执行....
# 函数执行结束....
# 2

4.2 装饰器的使用

  • 通过装饰器,可以在不修改原来函数的情况下来对函数进行扩展
  • 在开发中,我们都是通过装饰器来扩展函数的功能的
def start_end(old):
    # 用来对其他的函数进行扩展,是其他的函数可以在执行前打印开始执行,执行结束后打印执行结束
    # 创建一个新的函数
    def new_function(*args,**kwargs):
        print('开始执行....')
        # 调用被扩展的函数
        result = old(*args,**kwargs)
        print('执行结束。。。')
        return result
    return new_function
f = start_end(add)  # f接收的是函数对象new_function
r = f(1,2)   # r接收的是 result
print(f)  # <function start_end.<locals>.new_function at 0x0000024F223A29D8>
print(r)  # 3


# 例如像 start_end()  这一类函数我们称之为装饰器
# 通过装饰器,可以在不修改原来函数的情况下,来对函数进行扩展
# 在开发中,我们都是通过装饰器来扩展函数的功能
def fn():
    print('我是fn函数')
f = start_end(fn)
r = f()  
# 结果:
# 开始执行....
# 我是fn函数
# 执行结束。。。
print(f)  # <function start_end.<locals>.new_function at 0x0000022B7FAB29D8>
print(r)  # None
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值