闭包函数和装饰器

对于python来说,一切皆对象

函数引用

函数可以被赋值给一个变量

def print_content(data):
    print(f"传来的参数是:{data}")

print("print_content的内存地址是:", print_content)

fun_name = print_content
print("fun_name的内存地址是:", fun_name)
fun_name("函数被赋值给了fun_name")

执行结果为:

print_content的内存地址是: <function print_content at 0x000002453131EC20>
fun_name的内存地址是: <function print_content at 0x000002453131EC20>
传来的参数是:函数被赋值给了fun_name

闭包函数

闭包函数,函数中的函数,即在某个函数中,定义一个函数,该函数被称为当前函数的闭包函数;

  • 闭包的内部函数中,对外部作用域的变量进行引用,但无法修改外部函数的局部变量
  • 闭包可以保存当前的运行环境

示例:

def student_grade(grade):
    print(f"以下是{grade}年级的学生:")
    def student_info(name, gender):
        print(f"姓名:{name}, 性别:{gender}, 年级:{grade}")
    return student_info

grade3 = student_grade(3)
grade3("张三", "男")
grade3("李四", "男")
grade3("林婉婉", "女")

执行结果为:

以下是3年级的学生:
姓名:张三, 性别:男, 年级:3
姓名:李四, 性别:男, 年级:3
姓名:林婉婉, 性别:女, 年级:3

装饰器

装饰器其实也是函数,只是对已有的函数进行装饰
以下以统计函数执行时间为例子进行讲解。

函数作为参数

装饰器的原理实际上是将函数作为一个对象,以传参的方式传递给另外一个函数

import datetime

def count_exe_time(func):
    start_time = datetime.datetime.now()
    func()
    end_time = datetime.datetime.now()
    print(f"执行{func}的时间为:{end_time-start_time}")

def sum():
    index = 10000
    result = 0
    while index >= 0:
        result += index
        index -= 1
    print(f"相加结果为:{result}")

count_exe_time(sum)

执行结果:

相加结果为:50005000
执行<function sum at 0x000001D89831F760>的时间为:0:00:00.000996

从示例中可以看出,count_exe_time(func)是用来计算函数func执行时需要的时间,要计算出sum()函数的执行时间,需要将sum()的函数名作为参数传给count_exe_time函数,使用时,是调用count_exe_time函数,可读性差,毕竟每次去看看执行了哪个函数,都只能根据参数去识别。

装饰器的简单使用

为了解决 函数作为参数的问题,提高代码的可读性、维护和管理,python提供了装饰器进行使用。
装饰器注意要点:

  • 作为装饰器的函数,其参数最好只有1位,作为被装饰函数的参数。
  • 装饰器内需要有个内包函数,在执行了被装饰函数后,必须返回该内包函数
  • 如果某个函数需要使用对应的装饰器,只需要在对应的函数定义前一行加上:@装饰器名称
  • 装饰器可能会装饰多个函数,所以对于被装饰函数的参数是不确定的,在闭包函数中,参数最好使用(*args, **kwargs)(只是在闭包函数中,不是被装饰的函数)
不带参数的装饰器
import datetime

# 定义一个函数,作为装饰器,只传递一个参数
def count_exe_time(func):
    # 定义一个闭包函数,计算函数执行时间
    def timer():
        start_time = datetime.datetime.now()
        func()
        end_time = datetime.datetime.now()
        print(f"执行{func}的时间为:{end_time-start_time}")
    # 返回闭包函数,注意只有函数名,没有括号
    return timer

# 装饰器使用格式:@函数名
@count_exe_time
def sum():
    index = 10000
    result = 0
    while index >= 0:
        result += index
        index -= 1
    print(f"相加结果为:{result}")

# 直接根据对应的函数进行调用,不用通过装饰器函数来调用
sum()

执行结果为:

相加结果为:50005000
执行<function sum at 0x0000021DC0F3F760>的时间为:0:00:00.000999
带参数的装饰器
import datetime

def count_exe_time(func):
    # 为了兼容sum()和sum(num)这2个函数,将闭包函数及其函数内的func函数调用,均设置传入参数为不定长参数
    def inner(*args, **kwargs):
        start_time = datetime.datetime.now()
        # 被装饰的函数调用,参数为不定长参数
        func(*args, **kwargs)
        end_time = datetime.datetime.now()
        print(f"执行{func}的时间为:{end_time-start_time}")
    return inner

@count_exe_time
def sum():
    index = 10000
    result = 0
    while index >= 0:
        result += index
        index -= 1
    print(f"相加结果为:{result}")

@count_exe_time
def sum_with_params(num):
    index = num
    result = 0
    while index >= 0:
        result += index
        index -= 1
    print(f"相加结果为:{result}")

sum()
print("--------------------------")
sum_with_params(8000)

执行结果为:

相加结果为:50005000
执行<function sum at 0x000002199017F760>的时间为:0:00:00.001000
--------------------------
相加结果为:32004000
执行<function sum_with_params at 0x000002199017F9A0>的时间为:0:00:00.000999
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值