python3 装饰器原理以及应用小案例

目录

1、什么是装饰器

2、装饰器的特点

3、装饰器的原理以及实现步骤

4、装饰器的应用小案例

一、什么是装饰器

装饰器是python中一个很重要的概念,简单来说:从字面意思来讲,就是装饰,强化,对你的函数进行功能是的扩充,并且无需修改被修饰函数的代码,起到装饰、补充的作用

要了解装饰器,我们先了解下什么是闭包函数

闭包函数:在嵌套函数中,如果内部函数对外部函数的变量进行了引用并且返回内部函数,那么内部函数就是闭包函数

我们看一个闭包函数的简单案例,来理解闭包

#定义了func的外部函数,中有c局部变量
def func(a,b):
    c = 10
    def inner_func():#内部函数inner对外部函数变量c做了引用
        s = a + b + c
        print(s)
    print(locals())    #产看本地的变量
    return inner_func  #外部函数返回的是一个内部函数
    

x = func(3,6)          #内层函数返回值,用x接收
x()                    #x的值等于 x =inner_func,是一个函数,所以可以调用

闭包注意点:

1、内部函数可以访问外部函数的不可变变量,但是如果要修改不可变变量,则要加关键字nonlocal进行声明
        2、内部函数和外部函数中的变量代码是平级的
        3、内部函数只是做了声明,外部函数代码中要进行调用,才会执行内部函数代码
        4、内部函数修改全局变量的不可变变量,要加global关键字进行声明

  闭包应用小案例:计数器

def counter():
    i = 0
    def inner_func():
        nonlocal i
        i +=1
        print("执行第{}次".format(i))
    return inner_func

x = counter()

x()
x()
x()

      

二、装饰器的特点

1、函数作为参数

2、要有闭包的特点

装饰器的基本结构案例:



#定义装饰器,对房子进行装饰
def decorate(func):        #传输参数hourse为函数
    a = 100
    def wrapper():        #定义内部函数,并调用func
        func()
        print("开始装饰毛坯房")
        print("开始了{}地板".format(a))
        print("开始刷漆")
    return wrapper


@decorate                   #hourse是被装饰的函数,(在@下面就是被装饰的函数) decoreate就是装饰器

#简单定义一个毛坯房
def hourse():
    print("这个是一个毛坯房")

hourse()

我们来简单梳理下上面的执行加载过程:

1、hourse 是被装饰的函数

2、decorate是装饰器

3、开始执行decorate,然后decorate返回值赋值给hourse

我们通过案例来验证下上面的结论:


def decorate(func):
    a = 100
    print("开始进行装饰")
    def wrapper(*args,**kwargs):
        func(*args,**kwargs)
        print("一共铺砖{}块".format(a))
        print("开始进行刷漆")
        print("开始进行家具布置")
    print("装饰完成")
    print(wrapper,1)
    return wrapper
@decorate
def hourse():
    print("这是一个毛坯房")

print(hourse)
上面代码执行结果:


开始进行装饰
装饰完成
<function decorate.<locals>.wrapper at 0x0000022D01A70EA0> 1
<function decorate.<locals>.wrapper at 0x0000022D01A70EA0>

注意观察,得出如下

1、当我们去装饰hourse时,没有进行调用,只是打印hourse,你观察函数的内存地址,和指向的就是wrapper内部函数的地址

2、执行顺序。

2.1 执行decorate函数

2.2 加载wrapper,注意只是加载,但是没有执行

2.3 hourse作为实参传入到decorate中,并decorate的返回值赋值个hourse

当我们把  print(hourse)  改为调用 hourse():得到的结果是:

开始进行装饰
装饰完成
<function decorate.<locals>.wrapper at 0x0000023E47BF0EA0> 1
这是一个毛坯房
一共铺砖100块
开始进行刷漆
开始进行家具布置

进一步说明了我们上面的结论

 

我们进一步来说明,当我们被装饰的函数有参数,并且装饰器也有参数的情形:

def outer(a):
    def decorate(func):
        def wrapper(*args,**kwargs):
            func(*args,**kwargs)
            print("---->开始第{}块铺地板".format(a))
        return wrapper
    return decorate

        
        


@outer(a=10)
def house(ti):
    print("房子到期日期是{}".format(ti))
    
house('6月10日')

当三层函数嵌套(装饰器有参数):

1、outer函数最外层,用来接收装饰器的参数

2、decorate第二层,用来接收被装饰的函数func

3、最内层函数,用来接收被装饰的函数的实参,因为我们不确定实参个数,所以通常是使用*args 和**kwargs来进行接收实参

最后,我们来看一个应用的实际案例:

场景:当我们没有登录到淘宝,可以查看商品信息,但是添加到购物车时,就会提示让你登录,或者你访问淘票票进行查看电影,当你点击电影查看票务详情,就会提示让你登录,我们就看看这段使用装饰器该怎么实现

代码如下:

import  time

is_login = False

def login():
    username = input("请输入用户名:")
    password = input("请输入用户密码:")
    if username == 'admin' and password == '123456':
        return True
    else:
        return  False

#添加装饰器
def decorater(func):
    def wrapper(*args,**kwargs):
        global is_login
        if is_login:
            func(*args,**kwargs)
        else:
            print("用户没有登录,请登录")
            is_login = login()
    return  wrapper

@decorater
def pay(n):
    print("正在支付中.....")
    time.sleep(2)
    print("支付完成,一共支付了{}元".format(n))


pay(3000)
pay(800)




完结总结:装饰器是一个重要模块,后续再flask或Drango中会有很多应用,这里做个详细的复盘笔记,加深自己印象


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值