高阶函数

以函数作为参数或者以函数作为返回值返回的函数

lst = [1,2,3,4,5,6,7,8,9,10]
def fn2(i):   #求偶数函数
    if i % 2 == 0:
        return True
def fn(func,l):  #高阶函数(将函数作为参数)
      lst2=[]
      for n in l:
        if func(n):
            lst2.append(n)
    return lst2
print(fn(fn2,lst))

闭包

高阶函数的第二种,将函数作为参数返回
通过闭包可以创建一些只有当前函数能够访问的变量
可以将一些私有的重要的放到闭包当中(PS:相当于自我封装,只能通过内部访问来获取)

闭包形成条件

1.嵌套函数(在函数内再定义一个函数)
2.将内部函数作为返回值返回
3.内部函数使用外部函数的变量

#fn()函数内的代码块,即形成闭包,外部无法获取到fn()内的a值,只有fn2()内能够获取到
def fn():
    a = 10
    # 在函数内部在定义一个函数
    def fn2():
        print('我是fn2',a)
    # 将内部函数fn2作为返回值返回
    return fn2
r=fn()
print(r) #我是fn2 10 None(因为fn2()没有返回值)
print(a) # NameError: name 'a' is not defined
a=20
print(r) #我是fn2 10 None  函数外部修改a的值不影响函数内部的变量,因为不是同一个对象

匿名函数

语法:lambda 参数列表 : 返回值
主要用来代替一些简单的逻辑函数,并且只会使用一次,随时使用完随时被回收

def fn5(a,b):

    return a + b

print(fn5(1,2))
#上述简单逻辑函数可以被匿名函数lambda表示
fn5 = lambda a,b : a + b
print(fn5)  #<function <lambda> at 0x0000021758F52F28> 返回值是一个名为lambda的匿名函数
print(fn5(5,6)) #11
#或者lambda后直接跟实参值
fn6 = (lambda a,b : a + b)(10,50)
print(fn6)  #60
filter()函数

filter() 就是一个高阶函数 它需要将别的函数作为参数来传递,可以将我们的可迭代对象进行一个过滤,返回值是个可迭代的对象

lst = [1,2,3,4,5,6,7,8,9,10]
def fn4(i):
    if i % 3 == 0:
        return True
    return False
# filter(fn4,lst) 等价于 filter(lambda i : i % 3 == 0,lst)

装饰器的引入

概念

扩展函数内容

装饰器产生的原因
  1. 如果要修改的函数过多,修改起来会非常麻烦
  2. 不方便后期维护
  3. 这样做会违反ocp原则(开闭原则) 要求开放对程序的扩展,要求关闭对程序的修改
def fn():
    print('我是fn函数')
# 定义一个新的函数 就是对原函数进行的扩展
def fn2():
    print('函数开始执行')
    fn()
    print('函数执行结束')

装饰器的使用

作用

1.像类似于start_end(old)这种函数我们就称之为装饰器
2.通过装饰器可以在不修改原来的函数的情况下对函数进行扩展
3.在开发中,我们都是通过装饰器来扩展函数的功能的

# 定义一个函数 就是对其他函数进行扩展的 扩展的功能一个 是打印函数开始执行 一个是打印函数执行结束
def start_end(old): #old参数为扩展之前的函数
    # 内部创建了一个函数
    def new_function(*args,**kwargs): #针对参数的可扩展性
        print('函数开始执行')
        r = old(*args,**kwargs)
        print('函数执行结束')
        # 返回函数的执行结果
        return r
    # 返回新的函数
    return new_function  #返回值为扩展之后的函数对象

def fn():
    print('我是fn函数')
def add(a,b):
    r = a + b
    return r
f = start_end(fn)
print(f())
f2 = start_end(add)
print(f2(13,46))
使用方法

在定义完装饰器后,在扩展前的函数前加上@装饰器函数名

@start_end
def speak():
    print('Hello World')
speak()