一些关于python 装饰器的个人理解


Posted in Python onAugust 31, 2020

装饰器

本质是一个接受参数为函数的函数。
作用:为一个已经实现的方法添加额外的通用功能,比如日志记录、运行计时等。

举例

1.不带参数的装饰器,不用@

# 不带参数的装饰器
def deco_test(func):
  def wrapper(*args, **kwargs):
    print("before function")
    f = func(*args, **kwargs)
    print("after function")
    return f
  return wrapper

def do_something(a,b,c):
  print(a)
  time.sleep(1)
  print(b)
  time.sleep(1)
  print(c)
  return a

if __name__ == '__main__':
  # 不用@
  f = deco_test(do_something)("1","2","3")

输出:

before function
1
2
3
after function

个人理解:

相当于在 do_something 函数外面套了两个输出: before function 和 after function 。

2.不带参数的装饰器,用 @

# 不带参数的装饰器
def deco_test(func):
  def wrapper(*args, **kwargs):
    print("before function")
    f = func(*args, **kwargs)
    print("after function")
    return f
  return wrapper

@deco_test
def do_something(a,b,c):
  print(a)
  time.sleep(1)
  print(b)
  time.sleep(1)
  print(c)
  return a

if __name__ == '__main__':
  # 使用@
  f = do_something("1","2","3")

输出:

before function
1
2
3
after function

个人理解:

相当于执行 do_something 函数的时候,因为有 @ 的原因,已经知道有一层装饰器 deco_test ,所以不需要再单独写 deco_test(do_something) 了。

3.带参数的装饰器

# 带参数的装饰器
def logging(level):
  def wrapper(func):
    def inner_wrapper(*args, **kwargs):
      print("[{level}]: enter function {func}()".format(level=level, func=func.__name__))
      f = func(*args, **kwargs)
      print("after function: [{level}]: enter function {func}()".format(level=level, func=func.__name__))
      return f
    return inner_wrapper
  return wrapper

@logging(level="debug")
def do_something(a,b,c):
  print(a)
  time.sleep(1)
  print(b)
  time.sleep(1)
  print(c)
  return a

if __name__ == '__main__':
  # 使用@
  f = do_something("1","2","3")

输出:

[debug]: enter function do_something()
1
2
3
after function: [debug]: enter function do_something()

个人理解:

装饰器带了一个参数 level = "debug" 。

最外层的函数 logging() 接受参数并将它们作用在内部的装饰器函数上面。内层的函数 wrapper() 接受一个函数作为参数,然后在函数上面放置一个装饰器。这里的关键点是装饰器是可以使用传递给 logging() 的参数的。

4.类装饰器

# 类装饰器
class deco_cls(object):
  def __init__(self, func):
    self._func = func

  def __call__(self, *args, **kwargs):
    print("class decorator before function")
    f = self._func(*args, **kwargs)
    print("class decorator after function")
    return f

@deco_cls
def do_something(a,b,c):
  print(a)
  time.sleep(1)
  print(b)
  time.sleep(1)
  print(c)
  return a

if __name__ == '__main__':
  # 使用@
  f = do_something("1","2","3")

输出:

class decorator before function
1
2
3
class decorator after function

个人理解:

使用一个装饰器去包装函数,返回一个可调用的实例。 因此定义了一个类装饰器。

5.两层装饰器

# 不带参数的装饰器
def deco_test(func):
  def wrapper(*args, **kwargs):
    print("before function")
    f = func(*args, **kwargs)
    print("after function")
    return f
  return wrapper

# 带参数的装饰器
def logging(level):
  def wrapper(func):
    def inner_wrapper(*args, **kwargs):
      print("[{level}]: enter function {func}()".format(level=level, func=func.__name__))
      f = func(*args, **kwargs)
      print("after function: [{level}]: enter function {func}()".format(level=level, func=func.__name__))
      return f
    return inner_wrapper
  return wrapper

@logging(level="debug")
@deco_test
def do_something(a,b,c):
  print(a)
  time.sleep(1)
  print(b)
  time.sleep(1)
  print(c)
  return a

if __name__ == '__main__':
  # 使用@
  f = do_something("1","2","3")

输出:

[debug]: enter function wrapper()
before function
1
2
3
after function
after function: [debug]: enter function wrapper()

个人理解:

在函数 do_something() 外面先套一层 deco_test() 装饰器,再在最外面套一层 logging() 装饰器。

以上就是python 装饰器的一些个人理解的详细内容,更多关于python 装饰器的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python内置函数dir详解
Apr 14 Python
一波神奇的Python语句、函数与方法的使用技巧总结
Dec 08 Python
Python中列表元素转为数字的方法分析
Jun 14 Python
python队列通信:rabbitMQ的使用(实例讲解)
Dec 22 Python
python+opencv识别图片中的圆形
Mar 25 Python
python使用matplotlib库生成随机漫步图
Aug 27 Python
浅析python 中大括号中括号小括号的区分
Jul 29 Python
python序列类型种类详解
Feb 26 Python
python 用递归实现通用爬虫解析器
Apr 16 Python
写好Python代码的几条重要技巧
May 21 Python
DjangoRestFramework 使用 simpleJWT 登陆认证完整记录
Jun 22 Python
python脚本框架webpy模板控制结构
Nov 20 Python
Python常用模块函数代码汇总解析
Aug 31 #Python
PyTorch 导数应用的使用教程
Aug 31 #Python
PyTorch安装与基本使用详解
Aug 31 #Python
pycharm 添加解释器的方法步骤
Aug 31 #Python
解决Windows下python和pip命令无法使用的问题
Aug 31 #Python
Python函数__new__及__init__作用及区别解析
Aug 31 #Python
从零开始的TensorFlow+VScode开发环境搭建的步骤(图文)
Aug 31 #Python
You might like
PHP substr 截取字符串出现乱码问题解决方法[utf8与gb2312]
2011/12/16 PHP
php中Array2xml类实现数组转化成XML实例
2014/12/08 PHP
网页的分页下标生成代码(PHP后端方法)
2016/02/03 PHP
javascript 限制输入和粘贴(IE,firefox测试通过)
2008/11/14 Javascript
jquery中使用ajax获取远程页面信息
2011/11/13 Javascript
JS获取图片实际宽高及根据图片大小进行自适应
2013/08/11 Javascript
JavaScript中的apply和call函数详解
2014/07/20 Javascript
Bootstrap基本插件学习笔记之Popover提示框(19)
2016/12/08 Javascript
详解网站中图片日常使用以及优化手法
2017/01/09 Javascript
vue项目实现记住密码到cookie功能示例(附源码)
2018/01/31 Javascript
jQuery实现点击自身以外区域关闭弹出层功能完整示例【改进版】
2018/07/31 jQuery
从Vuex中取出数组赋值给新的数组,新数组push时报错的解决方法
2018/09/18 Javascript
解决vue单页面应用中动态修改title问题
2019/06/09 Javascript
js中offset,client , scroll 三大元素知识点总结
2019/09/11 Javascript
express中static中间件的具体使用方法
2019/10/17 Javascript
vue滚动插件better-scroll使用详解
2019/10/18 Javascript
详解js location.href和window.open的几种用法和区别
2019/12/02 Javascript
使用Mock.js生成前端测试数据
2020/12/13 Javascript
python二叉树的实现实例
2013/11/21 Python
Python中py文件引用另一个py文件变量的方法
2018/04/29 Python
Python Pandas批量读取csv文件到dataframe的方法
2018/10/08 Python
Pandas_cum累积计算和rolling滚动计算的用法详解
2019/07/04 Python
浅谈pytorch grad_fn以及权重梯度不更新的问题
2019/08/20 Python
pytorch 实现模型不同层设置不同的学习率方式
2020/01/06 Python
Tensorflow实现将标签变为one-hot形式
2020/05/22 Python
Python实现扫码工具的示例代码
2020/10/09 Python
python GUI计算器的实现
2020/10/09 Python
德国汽车零件和汽车配件网上商店:kfzteile24
2018/11/14 全球购物
大一学生职业生涯规划
2014/03/11 职场文书
2014年3.15团委活动总结
2014/03/16 职场文书
认购协议书范本
2014/04/22 职场文书
2014年教师教学工作总结
2014/11/08 职场文书
英文邀请函
2015/02/02 职场文书
天那边观后感
2015/06/09 职场文书
Python中threading库实现线程锁与释放锁
2021/05/17 Python
如何vue使用el-table遍历循环表头和表体数据
2022/04/26 Vue.js