Python-day10:装饰器详解、高阶函数、变量内存地址说明

本文深入探讨Python中的装饰器用法,详细解释了函数的内存地址机制,并介绍了高阶函数的概念。通过案例分析day10_case5()的运行结果,进一步理解Python函数的深层次运作。
摘要由CSDN通过智能技术生成

1、代码

# 2021年12月08日,第四周1~7
# !/usr/bin/env python
# -*- coding: utf-8 -*-
import time


def time_low_low(func):  # 计算函数运行时间
    start_time = time.time()
    func()
    stop_time = time.time()
    print("不使用装饰器:the func run time is %s" % (stop_time - start_time))
    return func


def day10_case():
    print("不使用装饰器")


# 装饰器:装饰器本质是函数(装饰函数),为函数添加功能,不修改原函数代码
# 装饰器 =》 高阶函数+嵌套函数
# 参考文章:https://www.cnblogs.com/wupeiqi/articles/4980620.html

def time_low(func):  # 计算函数运行时间
    # 错误装饰器示例
    # 此装饰器仅仅适用无传参与无返回值的函数,
    # 若对有传参的函数与有返回值的函数使用会出现bug或报错。
    # def warpper(): #若函数无参数传入,可以不输入*args, **kwargs,把注释去掉,调用day10_case0()可检验
    def warpper(*args, **kwargs):
        start_time = time.time()
        func()
        stop_time = time.time()
        print("装饰1:the func run time is %s" % (stop_time - start_time))

    return warpper


@time_low
def day10_case0():
    # 使用了错误装饰器
    print("使用了错误装饰器")


@time_low
def day10_case1(hint="参数传不进来"):
    # 使用了错误装饰器
    print("使用了错误装饰器")
    print(hint)
    return hint


def time_new(func):  # 计算函数运行时间
    # 正确的装饰器示例
    # 必须添加*args, **kwargs,否则报错
    def warpper(*args, **kwargs):
        start_time = time.time()
        # 1、必须添加*args, **kwargs,否则被装饰的函数无法传入参数
        # 2、必须使用一个变量承接函数返回值,若直接return func会返回一个函数的内存地址
        func1 = func(*args, **kwargs)
        stop_time = time.time()
        print("the func run time is %s" % (stop_time - start_time))
        # return func # 直接return func会返回一个函数的地址
        return func1  # 必须return func函数的返回值,否则被装饰的函数返回值为None

    return warpper
    # 函数可是看成变量,warpper可以看成变量,若没有调用,即是一堆字符串;
    # 例如匿名函数calc = lambda x:x*x; print(calc(10)); 输出100。
    # 若函数被调用,会先找到函数的内存地址,然后再运行。
    # 函数(装饰器)time_new(func)若被传入值(函数),
    # 会运行return warpper,因传入的func使得warpper(*args, **kwargs)变成一个完整函数,
    # 然后warpper函数体得以运行,然后再运行func函数体,从而构成一个装饰器

# 假设day10_case2地址为0xa,warpper地址为0xb
# @time_new等同于day10_case2 = time_new(day10_case2) = warpper;旧day10_case2地址0xa已传给参数func,
# 即新day10_case2地址为warpper的地址0xb,func的地址为旧day10_case2的地址0xa
# day10_case2地址=0xb;func的地址=0xa
# 执行完time_new()函数,然后执行day10_case2函数(地址0xb),即执行warpper()函数
# 执行warpper()函数到func(*args, **kwargs)时,即执行原day10_case2函数(地址0xa),然后继续运行至程序结束

@time_new
def day10_case2(*args):
    # 使用了正确装饰器
    # 注意:因为*args只传如一个参数,所以传入的实际值为元组(args,)
    # 若传入2个参数,传入的实际值为元组(args1,args2)
    print("使用了正确装饰器")
    print(args)
    return args


def day10_case3(*args):
    # 高阶函数示例
    print("我是函数3")
    return args


def day10_case4(args):
    # 高阶函数示例
    print("我是函数4")
    args()  # 若args传入函数day10_case3,则运行函数3
    return args


def day10_case5():
    # 变量内存地址说明
    x = 1
    y = x
    print("x的内存地址为:{0},y的内存地址为:{1}".format(id(x), id(y)))
    y = 1
    print("因y的值不变,所以x与y的内存地址不变,"
          "x的内存地址为:{0},y的内存地址为:{1}".format(id(x), id(y)))
    y = 2
    print("因y的值改变,y的内存地址改变,x的值不变内存地址不变;"
          "x的内存地址为:{0},y的内存地址为:{1}".format(id(x), id(y)))
    x = 2
    print("因x的值改变,x的内存地址改变,y的内存不变;因x与y的值相等,所以共用地址;"
          "x的内存地址为:{0},y的内存地址为:{1}".format(id(x), id(y)))


if __name__ == '__main__':
    day10_case_new = time_low_low(day10_case)  # 不使用装饰器计算函数运行时间,高阶函数
    # day10_case的内存地址将赋值给day10_case_new,time_low_low返回的day10_case是内存地址
    day10_case_new()  # 加上括号可直接运行day10_case()函数,因为day10_case_new与其共用一个内存地址
    # day10_case1()使用了错误装饰器@time_low,参数传不进去,返回值为空
    print(day10_case0())
    print(day10_case1(hint="case1传入参数"))
    # day10_case2()使用了正确装饰器@time_new,参数可传进去,返回值返回正常
    print(day10_case2("case2传入参数"))
    calc = lambda x: x * x  # 匿名函数
    print("calc匿名函数结果:", calc(10))
    print(day10_case4(day10_case3))  # 高阶函数示例,返回函数3的内存地址
    day10_case5()  # 变量内存地址说明

2、函数内存地址说明

3、高阶函数

 4、函数day10_case5()运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值