一.什么是装饰器

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

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

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

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

闭包中内部函数如何修改外部函数提供的变量? 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. Java一个文件上传工具类

    /** * 文件上传 * * @author cary * @since 2012-12-19 下午2:22:12 */ public class FileUploader { static fina ...

  2. FutureTask详解

    1 基本概念 1.1 Callable与Future Runnable封装一个异步运行的任务,可以把它想象成为一个没有参数和返回值的异步方法.Callable与Runnable类似,但是有返回值.Ca ...

  3. UI设计:掌握这6点,轻松0到1

    非科班出身能成为UI设计师吗? 答案是肯定的.世上无难事,只怕有心人.只要找对方法.坚持不懈,即便是零基础也能学好UI设计. 那么零基础学习UI设计,需要学习哪些知识?我们要从哪些地方学起?怎么系统学 ...

  4. 用个体软件过程(PSP)记录你的工作

    用个体软件过程(PSP)记录你的工作 首先,非常感谢大家对本门课程的学习所投入的时间和精力. 其次,已经进入数据时代,口说无凭,拿数据来.如果你认为你已经投入了大量精力在这门课程的学习和作业中,而且已 ...

  5. 2018.08.21 NOIP模拟 xorand(01trie)

    xorand 描述 有q次操作,每次操作是以下两种: 1. 加入一个数到集合中 2. 查询,查询当前数字与集合中的数字的最大异或值,最大and值,最大or值 输入 第一行1个正整数Q表示操作次数 接下 ...

  6. 第五章:动词(Les verbes)

    ★及物动词(Les verbes transitifs) 主语发出的动作作用于人或物,它又分为两类,直接及物动词和间接及物动词. ()直接及物动词:动词直接带宾语,不需要介词引导.如:         ...

  7. HDU 1242 Rescue (BFS+优先队列)

    题意:X代表卫兵,a代表终点,r代表起始点,.代表路,#代表墙,走过.要花费一秒,走过x要花费2秒,求从起点到终点的最少时间. 析:一看到样例就知道是BFS了吧,很明显是最短路径问题,不过又加了一个条 ...

  8. scrapy windows 安装

    windows 7 系统下参照官网安装总是会提示出错,现在整理一下安装的流程 1.安装 python 2.7,添加环境变量 C:\Python27\;C:\Python27\Scripts\; 在 C ...

  9. PhotoModeler Scanner教程

    Marking and Referencing 标记和校正 标记和校正是通过多张照片人工匹配共同特征的过程.点击一张图片的明显视觉特征,然后将它匹配到不同角度拍摄的其他图片的相同特征上. Approp ...

  10. 【转】Android贪吃蛇源代码

    /*TileView:tile有瓦片的意思,用一个个tile拼接起来的就是地图.TileView就是用来呈现地图的类*/ public class TileView extends View { /* ...