一些关于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使用mysqldb连接数据库操作方法示例详解
Dec 03 Python
Python最长公共子串算法实例
Mar 07 Python
python访问mysql数据库的实现方法(2则示例)
Jan 06 Python
Python守护进程和脚本单例运行详解
Jan 06 Python
python实现八大排序算法(2)
Sep 14 Python
Python将多份excel表格整理成一份表格
Jan 03 Python
Python中staticmethod和classmethod的作用与区别
Oct 11 Python
python简单贪吃蛇开发
Jan 28 Python
Python实战之制作天气查询软件
May 14 Python
python爬虫爬取网页数据并解析数据
Sep 18 Python
pandas 数据类型转换的实现
Dec 29 Python
Python绘画好看的星空图
Mar 17 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
php5数字型字符串加解密代码
2008/04/24 PHP
使用eAccelerator加密PHP程序
2008/10/03 PHP
PHP学习之输出字符串(echo,print,printf,print_r和var_dump)
2011/04/17 PHP
php中{}大括号是什么意思
2013/12/01 PHP
新浪SAE搭建PHP项目教程
2015/01/28 PHP
javascript 学习笔记(六)浏览器类型及版本信息检测代码
2011/04/08 Javascript
屏蔽网页右键复制和ctrl+c复制的js代码
2013/01/04 Javascript
JS鼠标滑过图片时切换图片实现思路
2013/09/12 Javascript
js分页代码分享
2014/04/28 Javascript
Javascript学习笔记之数组的构造函数
2014/11/23 Javascript
简介JavaScript中的unshift()方法的使用
2015/06/09 Javascript
点击页面任何位置隐藏div的实现方法
2016/09/05 Javascript
基于JSONP原理解析(推荐)
2017/12/04 Javascript
微信小程序实现通过双向滑动缩放图片大小的方法
2018/12/30 Javascript
JavaScript中this的全面解析及常见实例
2019/05/14 Javascript
vue+egg+jwt实现登录验证的示例代码
2019/05/18 Javascript
详解使用JWT实现单点登录(完全跨域方案)
2019/08/02 Javascript
vue中el-input绑定键盘按键(按键修饰符)
2020/07/22 Javascript
Vue 解决在element中使用$notify在提示信息中换行问题
2020/11/11 Javascript
[01:04:01]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS DT第一场
2014/05/24 DOTA
python 多进程通信模块的简单实现
2014/02/20 Python
Python库urllib与urllib2主要区别分析
2014/07/13 Python
对numpy和pandas中数组的合并和拆分详解
2018/04/11 Python
ubuntu16.04制作vim和python3的开发环境
2018/09/23 Python
python实现RabbitMQ的消息队列的示例代码
2018/11/08 Python
python-tornado的接口用swagger进行包装的实例
2019/08/29 Python
关于ZeroMQ 三种模式python3实现方式
2019/12/23 Python
美国男装连锁零售商:Men’s Wearhouse
2016/10/14 全球购物
美国知名艺术画网站:Art.com
2017/02/09 全球购物
巴黎卡诗美国官方网站:始于1964年的头发头皮护理专家
2017/07/10 全球购物
英国音乐设备和乐器商店:Gear4music
2017/10/16 全球购物
土木工程实习生自我鉴定
2013/09/19 职场文书
自我反省检讨书
2014/01/23 职场文书
先进党员事迹材料
2014/12/24 职场文书
感谢信怎么写
2015/01/21 职场文书
2015年班长个人工作总结
2015/04/03 职场文书