一些关于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实现全局变量的两个解决方法
Jul 03 Python
在Python的gevent框架下执行异步的Solr查询的教程
Apr 16 Python
使用pdb模块调试Python程序实例
Jun 02 Python
Perl中著名的Schwartzian转换问题解决实现
Jun 02 Python
Python的Flask框架中SQLAlchemy使用时的乱码问题解决
Nov 07 Python
修复CentOS7升级Python到3.6版本后yum不能正确使用的解决方法
Jan 26 Python
基于Django与ajax之间的json传输方法
May 29 Python
django 2.2和mysql使用的常见问题
Jul 18 Python
Python tcp传输代码实例解析
Mar 18 Python
Django-xadmin+rule对象级权限的实现方式
Mar 30 Python
浅谈PyTorch中in-place operation的含义
Jun 27 Python
详解pandas中利用DataFrame对象的.loc[]、.iloc[]方法抽取数据
Dec 13 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
WAR3重制版DOTA 5V5初体验
2020/04/09 DOTA
PHP mb_convert_encoding文字编码的转换函数介绍
2011/11/10 PHP
PHP关联链接常用代码
2012/11/05 PHP
PHP利用header跳转失效的解决方法
2014/10/24 PHP
一文看懂PHP进程管理器php-fpm
2020/06/01 PHP
javascript常用的正则表达式实例
2014/05/15 Javascript
JS表的模拟方法
2015/02/05 Javascript
灵活使用数组制作图片切换js实现
2016/07/28 Javascript
jquery插件bootstrapValidator表单验证详解
2016/12/15 Javascript
老生常谈的跨域处理
2017/01/11 Javascript
JavaScript实现简单的双色球(实例讲解)
2017/07/31 Javascript
JS实现将链接生成二维码并转为图片的方法
2018/03/17 Javascript
webpack file-loader和url-loader的区别
2019/01/15 Javascript
vue实现todolist基本功能以及数据存储功能实例详解
2019/04/11 Javascript
Vue脚手架编写试卷页面功能
2020/03/17 Javascript
JS自定义右键菜单实现代码解析
2020/07/16 Javascript
vue v-for出来的列表,点击某个li使得当前被点击的li字体变红操作
2020/07/17 Javascript
对python opencv 添加文字 cv2.putText 的各参数介绍
2018/12/05 Python
使用python绘制二维图形示例
2019/11/22 Python
pytorch实现focal loss的两种方式小结
2020/01/02 Python
python orm 框架中sqlalchemy用法实例详解
2020/02/02 Python
Python修改列表值问题解决方案
2020/03/06 Python
Django ForeignKey与数据库的FOREIGN KEY约束详解
2020/05/20 Python
Python使用for生成列表实现过程解析
2020/09/22 Python
乌克兰最大的家用电器和电子产品连锁店:Eldorado
2019/10/02 全球购物
创意爱尔兰礼物:Creative Irish Gifts
2020/01/29 全球购物
新闻专业本科生的自我评价分享
2013/11/20 职场文书
《童年的发现》教学反思
2014/02/14 职场文书
《小池塘》教学反思
2014/02/28 职场文书
婚前协议书怎么写
2014/04/15 职场文书
国际贸易专业求职信
2014/06/04 职场文书
感情真挚的毕业生求职信
2014/07/19 职场文书
党员对照检查材料思想汇报
2014/09/16 职场文书
煤矿百日安全活动总结
2015/05/07 职场文书
淮海战役观后感
2015/06/11 职场文书
简单谈谈Python面向对象的相关知识
2021/06/28 Python