一.什么是装饰器

装饰器是用来给函数动态的添加功能的一种技术,属于一种语法糖。通俗一点讲就是:在不会影响原有函数的功能基础上,在原有函数的执行过程中额外的添加上另外一段处理逻辑

二.装饰器功能实现的技术基础--闭包

什么是闭包?闭包就是:一个内部函数被一个外部函数当做返回值进行返回,并且内部函数引用了外部函数提供的变量, 此时将内部函数和引用的外部变量构成的整体称为闭包

闭包的特征?闭包有一个明显的特征就是:引用了外部变量的闭包能够让外部函数不被释放,如果外部函数被释放,就会导致内部函数访问变量时出错

闭包中内部函数如何修改外部函数提供的变量? python3 如果要在闭包内修改外部函数提供的变量,需要使用(nonlocal 变量名称)  进行声明变量不是本地变量,才能进行更改 , python2 中,需要在闭包外先将变量添加到一个列表里,再在闭包内通过下标取出变量,然后进行更改使用。

三.装饰器的使用场景

  引入日志
  函数执行时间统计
  执行函数前预备处理
  执行函数后清理功能
  权限校验等场景
  缓存

三.不带参的装饰器的使用与流程分析

装饰阶段:调用外层函数 (在调用被装饰函数前,已经经历装饰阶段)
运行阶段:调用内层函数和 内层函数的函数体中的func指向的 装饰器下的函数 (运行阶段就是调用被装饰函数的时候)
#coding=utf-8

from django.shortcuts import redirect
from django.http import HttpResponseRedirect
from rest_framework.response import Response def login(func): # 登录验证装饰器,如果未登录就转到登录页面
def login_func(request, *args, **kwargs)
if user_id in request.session
return func(request, *args, **kwargs)
else:
返回还是一个response对象,可以用来设置cookie,session等
redi = HttpResponseRedirect('./user/login')
# 设置cookie,当用户尚未登录时就进行需要登录后才能进行的操作,
# 就先记住用户的当前所处的页面,登录时,通过取回cookie则将用户登录前所处的页面返回
redi.set_cookies('url', request.get_full_path())
return redi
return login_func # 返回时使用了变量名称 api_list 进行接收 @login
def api_list(request):
return Response(status=status.HTTP_200_OK)

api_list(request) # 假设存在这么一个调用逻辑。当然了,在实际的接口,并不是我们开发人员手动去调用的,有用户请求了才会触发。
# request.get_full_path() 获取带参数的当前请求所在的页面的url
# request.path 获取去掉参数的当前请求所在的页面的url 流程说明:
  1.装饰阶段
  首先,会存在这么一个执行流程(这是解释器去进行的):
  api_list = login(api_list),
  将被装饰的函数的引用进行传参,调用装饰器的外层函数,返回内层函数的引用, 返回值使用了被装饰函数的函数名称进行接收,此时的状态就是:
  api_list 指向了 原来 login_func 包含的函数体,func 指向了 原来api_list所指向的函数体,注意是 原来!
  2.运行阶段
    当使用 ret = api_list(request) 进行函数的调用时,因为 api_list 已经指向了 原来 login_func 所包含的函数体,也就是装饰器的内层
    函数。所以,装饰器的内层函数开始执行,func被调用,因为此时 func 指向了原来 api_list 所包含的函数体,最后,被装饰函数得到执行

注意:内层函数也同样要接收 被装饰函数所接收了的参数

四.带参的装饰器的使用与流程分析

# 装饰阶段(装饰阶段时解释器自动进行这段逻辑的):
# 1.beter = outer("lowman"), 结果是创建出新的装饰器 @beter,然后继续进行装饰,就是下面第二步
# 2.zhuangshi = beter(zhuangshi),结果为 zhuangshi 引用指向 原来 inner 的函数体, func 指向了 原来 zhuangshi 的函数体
# 运行阶段:
# 1.调用 zhuangshi(last_name) 时,实际调用的是 inner(last_name, *args, ** kwargs)
# 2.调用 inner 内层函数体中的 func(last_name, * args, **kwargs) 时,实际调用的是 原来 def zhuangshi(last_name) 的函数体
# 带参与不带参的使用区别:
# 带参装饰器与不带参的装饰器的区别仅仅就是带参装饰器可以实现通过装饰器向闭包中传递参数,仅此而已。 def outer(item): def beter(func): first_name = item def inner(last_name, *args, ** kwargs):
ret = func(last_name, * args, **kwargs)
return first_name + ret return inner return beter @outer("lowman")
def zhuangshi(last_name):
return last_name ret = zhuangshi("isbusy") # 调用zhuangshi函数,实际调用的是 内层函数inner, 随后 func 函数被执行, 被装饰函数最终也得以执行
print(ret) # 打印结果: lowmanisbusy

注意:

多个装饰器装饰一个函数:
# 1.装饰阶段:先装饰 内层装饰器,再装饰 外层装饰器;
# 2.运行阶段:先执行 外层装饰器,再执行 内层装饰器;

python 带参与不带参装饰器的使用与流程分析/什么是装饰器/装饰器使用注意事项的更多相关文章

  1. python 全栈开发,Day11(函数名应用,闭包,装饰器初识,带参数以及带返回值的装饰器)

    一.函数名应用 函数名是什么?函数名是函数的名字,本质:变量,特殊的变量. 函数名(),执行此函数. python 规范写法 1. #后面加一个空格,再写内容,就没有波浪线了. 2.一行代码写完,下面 ...

  2. python语法糖之有参装饰器、无参装饰器

    python的装饰器简单来说就是函数的一种形式,是为了扩展原来的函数功能而设计的. 装饰器的特别之处在于它的返回值也是一个函数,可以在不改变原有函数代码的基础上添加新的功能 # 先定义一个函数及引用# ...

  3. Python:高级主题之(属性取值和赋值过程、属性描述符、装饰器)

    Python:高级主题之(属性取值和赋值过程.属性描述符.装饰器) 背景 学习了Javascript才知道原来属性的取值和赋值操作访问的“位置”可能不同.还有词法作用域这个东西,这也是我学习任何一门语 ...

  4. Python面试题集合带答案

    目录 Python基础篇 1:为什么学习Python 2:通过什么途径学习Python 3:谈谈对Python和其他语言的区别 Python的优势: 4:简述解释型和编译型编程语言 5:Python的 ...

  5. 如何写一个Python万能装饰器,既可以装饰有参数的方法,也可以装饰无参数方法,或者有无返回值都可以装饰

    Python中的装饰器,可以有参数,可以有返回值,那么如何能让这个装饰器既可以装饰没有参数没有返回值的方法,又可以装饰有返回值或者有参数的方法呢?有一种万能装饰器,代码如下: def decorate ...

  6. Windows下用Python 3.4+自带的venv模块创建虚拟环境

    Python 3.4+自带了venv模块,用于创建虚拟环境,每个虚拟环境都可以安装一套独立的第三方模块. 本文在Windows 10上操作. 1.创建一个虚拟环境: D:\>mkdir test ...

  7. python实现的、带GUI界面电影票房数据可视化程序

    代码地址如下:http://www.demodashi.com/demo/14588.html 详细说明: Tushare是一个免费.开源的python财经数据接口包.主要实现对股票等金融数据从数据采 ...

  8. Python 实现的、带GUI界面的词云生成器

    代码地址如下:http://www.demodashi.com/demo/14233.html 详细说明: "词云"就是数据可视化的一种形式,给出一段文本,根据文本中词语的出现频率 ...

  9. python元组声明要带逗号

    python元组声明要带逗号 t2, t3, t4 = (2), (2,),() print(type(t2),type(t3), type(t4)) #<class 'int'> < ...

随机推荐

  1. PAT 1054 求平均值 (20)(代码+思路+测试用例)

    1054 求平均值 (20)(20 分) 本题的基本要求非常简单:给定N个实数,计算它们的平均值.但复杂的是有些输入数据可能是非法的.一个"合法"的输入是[-1000,1000]区 ...

  2. OpenGLES.gpus_ReturnNotPermittedKillClient

    在iOS中,使用OpenGLES不当引起的crash:“gpus_ReturnNotPermittedKillClient” https://developer.apple.com/library/i ...

  3. linux中如何检测设备驱动模块是否存在

    linux系统中的设备驱动是否安装好一般检查几个方面:1.系统日志.嵌入式系统多是直接dmesg一下,看有没有设备关键字相关的出错信息(通用系统可检查/var/log/messages文件).2.已加 ...

  4. Banner中文字怎么排版才好看?

    今天这命题,相信有很多人提出过疑问,一个好的文字排版会给你的作品增添色彩,我们先看看好的作品是怎样的. 看完这些图大家都能感觉出来这是一个好的作品,大家天生就对美和丑有一定的区分. 其实文字排版也好, ...

  5. 连接redis

  6. 设计神器 - 摹客设计系统上线了 | 晒出你的设计规范,赢iPad Pro!

    在国内,设计规范也许还是个不太常用的概念,但是如果你正好有参与互联网公司的产品设计,你应该早就已经体会到设计规范的重要性了.UI设计师总是要花费大量的时间和精力向开发描述一大堆设计细节,但是产品最后呈 ...

  7. db2学习笔记

    a.服务端安装 v11.1_win64_expc.zip 官网下载 b.客户端安装 Toad for DB2 Freeware 6.1 百度找找 .建数据库 create database HRA_G ...

  8. Sublime Text webstorm等编译器快速编写HTML/CSS代码的技巧

    <!DOCTYPE html> Sublime Text webstorm等编译器快速编写HTML/CSS代码的技巧--summer-rain博客园 xiayuhao 东风夜放花千树. 博 ...

  9. [开源,学习,分享]UWP第三方简书客户端分享

    简介 Windows10正式版发布到现在,我利用零零碎碎的一些时间对UWP进行一些学习,也基于这门技术开发了一个第三方的简书App. 基本界面 优酷视频: http://v.youku.com/v_s ...

  10. 2018.09.15 poj2117Electricity(割点)

    传送门 其实求一个图删除一个点之后,联通块最多有多少. 直接tarjan求割点更新答案就行了. 但注意原图不一定连通. 代码: #include<iostream> #include< ...