装饰器详解对小白友好

装饰器实质是函数,只是应用较广,所以就直接叫做装饰器,又叫做语法糖

一、闭包的概念

def func():
    var = 'hello,world' 
    print(var)
    def inner():
        var = 'GitHub'
        print(var)
# 执行
func()      

在这里插入图片描述
这个里面包含两个知识点,一是函数名其实也是一种变量,func这个函数名指向其所对应的函数封装内容,而在func函数中,又在内定义了一个inner函数。
函数定义后通过 函数名 + () 有的需要传入参数)调用,而此处调用的是func()函数,先赋值变量var,输出,再定义函数inner(),但inner函数并没有被调用,所以打印的结果是hello,world
如下图:
在这里插入图片描述
那怎么样才能调用inner呢?
先试试直接调用

inner()

在这里插入图片描述

这会出错,说变量 inner 未被定义,这很好理解,因为 inner 这个函数名本身就是一个变量,那么就可以知道它是局部变量,只在 func() 内起作用。所以这个 inner() 函数就是一个闭包,它在func() 外不能被直接访问。
那到底该怎么做呢?
我们可以通过返回值来调用inner(),具体如下:

def func():
    var = 'hello,world'
    print(var)
    def inner():
        var = 'GitHub'
        print(var)
    return inner

i = func()
i()
print("func:{} , inner:{}".format(func,i))

在这里插入图片描述

可以看到此次输出了 GitHub,这是因为func,inner都是变量,指向其所代表的函数。那么将返回值 inner 其所指向的地址赋值给另一个变量i,再通过 i() 就能访问到闭包 inner() 。
装饰器本质上就是一个闭包。

二、装饰器

顾名思义,装饰器就是用来修饰某个函数,在不改变原来方法代码和调用方式的前提下,额外的附加其他的功能和属性。
先来看个例子

def timer(func):
    def inner():        # 闭包函数
        func()
        print('Hello,world')
    return inner

def fun1():
    print('GitHub')

fun2 = timer(fun1)
fun2()

fun1 = timer(fun1)
fun1()

在这里插入图片描述

具体过程是先以 fun1 为参数 调用 timer() 返回 inner ,并赋值给名为 fun2 的变量,再用fun2 + () 去调用 inner 所指向的闭包,若把 fun2 换成 fun1,则我们实现了不改变一个函数的代码,给一个函数增加功能但不改变其调用方式。
现在来修改一下

def timer(func):
    def inner():
        func()
        print('Hello,world')
    return inner

@timer 
def fun1():
    print('GitHub')
    
fun1()    

在这里插入图片描述

可以看到这里,调用fun1() 在结果中也打印出了 Hello,world ,所以 @timer 的作用等效于 fun1 = timer(fun1) ,即把 fun1作为参数传递给装饰器 timer() ,返回闭包函数名所指向的地址给 fun1,最后再通过fun1 调用。
更进一步,还可以新建一个新文件,导入刚才的模块,如下
from sfd import fun1 # sfd 是我刚才写入代码的文件名
fun1()

在这里插入图片描述

结果不变
除此之外,多个装饰器也可以装饰同一个函数。

发布了2 篇原创文章 · 获赞 3 · 访问量 63

猜你喜欢

转载自blog.csdn.net/qq_44447544/article/details/104518967