小学二年级也能学会的python装饰器的使用及理解(python高级进阶)

想要了解装饰器,你首先要了解一个概念-----闭包.装饰器的实现原理和闭包几乎是一模一样的..所以说,不要着急,跟随我的脚步,先跟着我理解闭包..之后直接使用装饰器...

需要具备的知识基础:

  •         1.python的多值参数
  •         2.python中一切皆对象(包括函数)

python装饰器的用武之地:

                           :::::::::::::::::::::::::::::::::先进入情境:::::::::::::::::::::::::::::

           某年某月某日假设你有一个如下的函数    

def fun():
    pass

        此时为了性能优化的需求,你想要知道这个函数运行需要多长的时间.那么你可能会想到这么写

      

import time
def fun():
    t_1=time.time()
    pass
    t_2=time.time()
    all_time=t_2-t_1#即为程序运行所需的总时间

.....OK,一个函数看起来这样写也无妨,,,但是,假如让你测试二十多个乃至几百个函数的运行时间,你再这样写.....你不觉得麻烦吗?????

从而python的装饰器或者说闭包的概念就来了.....

作用:装饰器和闭包,可以辅助你用更加简洁易懂的代码内用来丰富你函数的功能..

比如说:你是一个自律的baby,你喜欢健身..那么你需要一直把哑铃带在身上吗???你要吃饭,你需要一直把碗装在身上吗???不需要吧..健身吃饭这些我们也需要,只不过需求的频率不算太高,跟你的呼吸,看视频用眼的频次比起来可差太多了吧.所以嘛,你自己好好品品

用处:

        1.简化代码内容

        2.增加被装饰函数的功能

只要满足以上两个需求,你就有理由来使用装饰器了.并且使用装饰器也会让你写的代码逼格很高有木有???(手动滑稽)

先来了解第一个概念

一.闭包

         我们知道函数也是对象.然而函数名内部就存着该函数的内存地址..

        而闭包一般形式就是一个外部函数outer_fun()嵌套一个或多个内部函数inner_fun(),,且内部函数可以访问外部函数的局部变量(即使外部函数已经调用完毕),并且外部函数会return inner_fun

闭包特点:

        1.inner_fun()可以访问outer_fun()的局部变量,即使outer_fun()已经调用完毕并且销毁

        2.inner_fun()甚至可以改变outer_fun()的局部变量,不过需要结合nonlocal来声明一下这个局部变量

#一个简单的闭包函数
def outer_fun(x):
    z=3
    def inner_fun(y):
        return x+y+z
    return inner_fun

#调用这个闭包函数
closure_fun=outer_fun(10)
value=closure_fun(5)
print(value)
'''运行结果value是18'''

(假设我想修改z的值,那么我需要再inner_fun()里面先写上'nonlocal z'声明一下,之后再给z赋值)

接下来,你跟着我的思路,一起来理解一下闭包函数形式下实现的和装饰器一模一样的功能(以此来理解装饰的内部运行)

装饰器本质也是函数,并且装饰器语法实现的和用闭包实现的装饰器功能是完全等价的

第一位上场的是我们的主要功能函数(未来的被装饰函数)

#作用是计算的n的阶乘
def n_factorial(n):
    if n < 0:
        return "n不能是负数"
    elif n == 0 or n == 1:
        return 1
    else:
        result = 1
        for i in range(2, n+1):
            result *= i
        return result

第二位上场的是我们的闭包函数(未来的装饰器函数)

def calculate_time(fun):
    def wrapper(*args):
        t_1 = time.time()
        n = fun(*args)#这个函数以外的都是我们添加的计算时间的功能的实现
        t_2 = time.time()
        print("程序运行所需时间为:{}".format(t_2 - t_1))
        return n
    return wrapper

第三位上场的是我们的闭包函数的调用方法

new_n_factorial=calculate_time(n_factorial)
i=new_n_factorial(20)
print(i)

上述的执行步骤:

        1.(从第三位看起)先调用了calculate_time()函数,并传入了参数n_factorial.(我们之前说了函数名包含了函数的地址,所以相当于参数是函数地址)

                1.1进入calculate_time函数,并传入n_factorial参数(其实就是fun,只需要在fun前面加上一个括号就可以调用了)

                1.2执行了def wrapper(*args)的操作.(注意:只是执行了定义函数的操作,没有调用,没有调用就是没有启用函数.....比较重要的是,其实在执行定义函数的过程中,将fun传了进去.那个wrapper函数里面的fun(*args)其实就是完完全全等价于n_factorial函数的...因为函数地址都是一样的..所以,你再转过来头看一下,这个wrapper()函数是不是就是添加了额外功能的n_factorial()函数..所以我们的下一个目标就是执行这个wrapper函数)

                1.3return wrapper(可见,return的是wrapper的函数地址值,因此我们的下一步就是去调用他啦..怎么调用呢?只要你的对象是函数对象,只需要在变量名之后加一个()并传入参数就可以调用了)

        2.return的wrapper被new_n_factorial变量接收..(所以此时,就可以知道这个wrapper()函数是完完全全等价于new_n_factorial()函数的...所以你想理解new_n_factorial()函数的过程,直接看wrapper()函数的过程就可以了...你品品,你细品)

        3.调用new_n_factorial()并传入参数20

                3.1开始执行new_n_factorial()...执行过程参考wrapper()函数的内部定义

        4.执行完new_n_factorial()后return n被i接受

        5.最后print(i),结束

闭包形式过程总结:

    上述函数扮演的角色:

          1.n_factorial():主要功能函数..

          2.calculate_time)():将wrapper()函数与n_factorial()函数绑定起来的函数..

          3.wrapper():相当于加了额外功能的n_factorial()函数..

        

********************************分界线****************************************

二.装饰器

接下来我们引入装饰器,及其语法

装饰器使用步骤:

        1.分清  被装饰函数  和  装饰器函数  并写好代码

        2.在被装饰函数的上方一行写上'@'+'装饰器函数函数名'(例如:装饰器函数名字为haha(),那么被装饰函数上方就要写'@haha')

        3.调用的时候,直接用  被装饰函数  的函数名调用即可

代码如下:

def calculate_time(fun):
    def wrapper(*args):
        t_1 = time.time()
        n = fun(*args)#这个函数以外的都是我们添加的计算时间的功能的实现
        t_2 = time.time()
        print("程序运行所需时间为:{}".format(t_2 - t_1))
        return n
    return wrapper

@calculate_time'''装饰器语法'''
def n_factorial(n):
    if n < 0:
        return "n不能是负数"
    elif n == 0 or n == 1:
        return 1
    else:
        result = 1
        for i in range(2, n+1):
            result *= i
        return result
n_factorial_value=n_factorial(10000)

所以可见,用装饰器写代码大大简化看闭包形式的写法..并且闭包形式的写法大大简化了为主要功能函数(即被装饰函数)添加额外功能的写法

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值