第四十一次总结:装饰器,高阶函数,多值传参,闭包,拆包

本文深入探讨了高阶函数的概念,包括函数作为参数和返回值的使用,以及闭包的特性。进一步讲解了装饰器的原理和应用,演示了如何通过装饰器增强函数功能而不修改原函数代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

高阶函数

什么是高阶函数

1,接收的参数,是一个函数名(是一个函数的引用)

2,函数的返回值,是一个函数名

满足任一条,就是高阶函数

 

情况一

"""
高阶函数之,函数接收的参数是一个函数名
"""
​
def eat():
    print('吃肉')
​
​
def func(f):
    # f = eat
    f()  # eat()
    
func(eat)

 

 

情况二

"""
高阶函数之,函数的返回值是一个函数名
"""
def run():
    print('在跑')
​
def eat():
    print('吃肉')
    return run
​
​
r = eat()  # r = run
r()  # run()

 

 

函数名的本质

函数名本质就是一个标识符

函数体才是函数的本体

函数名会指向函数本体

如果把一个函数名赋值给另一个变量

那么通过这个变量加上括号

也可以调用函数

 

函数的嵌套

函数里面定义函数

 

"""
函数的嵌套
"""
​
def cat():
    def run():
        print('在跑')
    run()
​
cat()

 

 

闭包

首先给出闭包函数的必要条件:

  • 闭包函数必须返回一个函数名

  • 闭包函数返回的那个函数必须引用父级函数变量(一般不能是全局变量)

 

闭包

1,它是一个高阶函数

因为外部的函数返回值是一个函数名(内部函数)

2,它是一个函数的嵌套

外部函数里面又定义了内部函数

3,内部的函数要用到外部函数的局部变量

 

闭包模型

def outer():
    name = "张三"
    def inner():
        print(name)
    return inner   # 高阶函数
​
m = outer()
m()

 

局部变量的两种形态

局部变量的特点

生命,从函数执行,到函数结束

 

形态1,函数内部直接通过赋值方式定义的变量

它就是一个局部变量

本例中的age就是一个函数中的局部变量

def func():
    age = 18
    print(age)
​
​
func()

 

形态2,通过形参方式接收的数据也是局部变量

本例中的age就是一个局部变量

实参的数据赋给形参的过程

就相当于,在函数的内部定义

age = 18

最终的效果和形态一是一样的

def func(age):
    print(age)
​
func(18)

 

外部函数带参数的闭包

 

def outer(name):
    # name = "吕布"
    def inner():
        print(name)
    return inner
​
m = outer("吕布")
m()

 

三层函数闭包

def func():
    name = "李白"
    def outer(name):
        def inner():
            print(name)
        return inner
    return outer
​
name = "赵云"
​
f = func()
o = f(name)
o()

 

 

def func(age):
    def outer(name):
        def inner():
            print(name)
            print(age)
        return inner
    return outer
​
f = func(18)
o = f("刘备")
o()

 

 

新增的需求

为函数统计耗时

# 一个已经开发好的项目
# 需要拓展功能
# 要求每一个函数在执行后
# 都输出一下耗时
#
# 如何解决
​
def add_many_num():
    isum = 0
    for i in range(100000):
        isum += i
    print(isum)
​
add_many_num()

 

 

解决一

# 方案1
# 在函数内加入功能
​
import time
​
def add_many_num():
    start = time.time()
    isum = 0
    for i in range(100000):
        isum += i
    print(isum)
    end = time.time()
    print('耗时', end-start)
​
add_many_num()
​
# 问题
# 修改了函数内部的代码,容易造成报错

 

 

解决2

# 方案2
# 利用高阶函数
# 不修改原来的代码
​
import time
​
def add_many_num():
    isum = 0
    for i in range(100000):
        isum += i
    print(isum)
​
​
def outer(func):
    start_time = time.time()
    func()
    end_time = time.time()
    print('耗时', end_time - start_time)
​
# outer(add_many_num)
add_many_num()
​
# 问题
# 功能解决了,但是函数的调用方式变了
# 如果要运行拓展了功能的函数,必需修改调用方式

装饰器

装饰器的本质就是一个函数

 

语法糖

语法糖(Syntactic sugar): 计算机语言中特殊的某种语法 这种语法对语言的功能并没有影响 对于程序员有更好的易用性 能够增加程序的可读性

简而言之,语法糖就是程序语言中提供的一种手段和方式而已。 通过这类方式编写出来的代码,即好看又好用,好似糖一般的语法。固美其名曰:语法糖

 

格式

@dec

def func():

pass

 

相当于执行了下面的代码

func = dec(func)

 

调用方式不改变

func()

 

 

装饰器的进阶

位置不正确时

# 会报错的情况
# 装饰器写在了后面
​
import time
​
@outer  #add_many_num = outer(add_many_num)
def add_many_num():
    isum = 0
    for i in range(100000):
        isum += i
    print(isum)
​
​
def outer(func):
    def inner():
        start_time = time.time()
        func()
        end_time = time.time()
        print('耗时', end_time - start_time)
    return inner
​
​
add_many_num()

 

装器形态还原

需要明确

只要解释器读到了装饰器所定久的函数那一行

就会自动的执行一下一个代码。。。。

# 会报错的情况
# 装饰器写在了后面
​
import time
​
​
def outer(func):
    print('.....')
    def inner():
        start_time = time.time()
        func()
        end_time = time.time()
        print('耗时', end_time - start_time)
    return inner
​
​
@outer  # 相当于 add_many_num = outer(add_many_num)
def add_many_num():
    isum = 0
    for i in range(100000):
        isum += i
    print(isum)
​
add_many_num()

 

被修饰的函数有返回值时

"""
有一个参数的时候
"""
import time
​
def outer(func):
    def inner(name):
        start_time = time.time()
        res = func(name)
        end_time = time.time()
        print('耗时', end_time - start_time)
        return res
    return inner
​
@outer  # 相当于 add_many_num = outer(add_many_num)
def add_many_num(name):
    isum = 0
    print(name)
    for i in range(100000):
        isum += i
    print(isum)
    return 'ok'
​
res = add_many_num("周泰")
print(res)

 

 

复习多值传参

def func(*args, **kwargs):
    print('hello')
    print(args,type(args))
​
    print(kwargs,type(kwargs))
func(1,2,3, name="张三", age=18)

 

 

拆包复习

拆包元组

函数调用的时候

def func(a,b):
    print(a,b)
​
 t = (1,2)
 func(*t)  #func(1,2)
# func(1,2)

 

拆包字典

函数调用的时候

def func2(name=3):
    print(name)
​
d = {"name":"zs"}
func2(**d)
# func2(name="zs")

 

 

函数转发多值传参

 

args元组

形态1

def func2(a,b):
    print('a',a)
    print('b',b)
​
​
def func1():
    t = (1,2)
    func2(*t)  # func2(1,2)
​
func1()

 

形态2

def func2(a,b):
    print('a',a)
    print('b',b)
​
​
def func1(*t):
    # t = (1,2)
    func2(*t)  # func2(1,2)
​
func1(1,2)

 

 

kwargs字典

def func2(name="张飞"):
    print(name)
​
​
def func1(**kwargs):
    # kwargs = {"name" : "吕布"}
    func2(**kwargs)  # func2(name = "吕布")
​
func1(name = "吕布")

 

万能装饰器

需要牢记的

def outer(func):
    def inner(*args, **kwargs):
        print('前面的')
        res = func(*args, **kwargs)
        print('后面的')
        return res
    return inner

 

多层装饰器

理解装饰顺序

"""
双层装饰器体验
"""
import time


def outer(func):
    @timer  # inner = timer(inner)
    def inner(*args, **kwargs):
        print('前面的')
        res = func(*args, **kwargs)
        print('后面的')
        return res
    return inner


def timer(func):
    print('.....')
    def inner():
        start_time = time.time()
        func()
        end_time = time.time()
        print('耗时', end_time - start_time)
    return inner


@timer   # xxx = timer(xxx)
@outer   # add_n_num = outer(add_n_num)
def add_n_num():
    n = 0
    for i in range(100000):
        n += i
    print(n)

add_n_num()  # inner()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值