一些关于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 调用c语言函数的方法
Sep 29 Python
Python创建二维数组实例(关于list的一个小坑)
Nov 07 Python
详解python string类型 bytes类型 bytearray类型
Dec 16 Python
Python机器学习之K-Means聚类实现详解
Feb 22 Python
Python爬虫beautifulsoup4常用的解析方法总结
Feb 25 Python
Django 中自定义 Admin 样式与功能的实现方法
Jul 04 Python
解析python实现Lasso回归
Sep 11 Python
Python用input输入列表的实例代码
Feb 07 Python
python 数据库查询返回list或tuple实例
May 15 Python
python中selenium库的基本使用详解
Jul 31 Python
使用Python制作一个数据预处理小工具(多种操作一键完成)
Feb 07 Python
Python中X[:,0]和X[:,1]的用法
May 10 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
关于文本留言本的分页代码
2006/10/09 PHP
PHP 中dirname(_file_)讲解
2007/03/18 PHP
PHP容易被忽略而出错陷阱 数字与字符串比较
2011/11/10 PHP
smarty内置函数config_load用法实例
2015/01/22 PHP
PHP生成可点击刷新的验证码简单示例
2016/05/13 PHP
ThinkPHP发送邮件示例代码
2016/10/08 PHP
浅谈php中curl、fsockopen的应用
2016/12/10 PHP
PHP实现登陆并抓取微信列表中最新一组微信消息的方法
2017/07/10 PHP
Laravel框架中缓存的使用方法分析
2019/09/06 PHP
laravel orm 关联条件查询代码
2019/10/21 PHP
Laravel 集成微信用户登录和绑定的实现
2019/12/27 PHP
javascript+css 网页每次加载不同样式的实现方法
2009/12/27 Javascript
用JQuery实现表格隔行变色和突出显示当前行的代码
2012/02/10 Javascript
自定义百度分享的分享按钮
2015/03/18 Javascript
详解AngularJS controller调用factory
2017/05/19 Javascript
Three.js如何用轨迹球插件(trackball)增加对模型的交互功能详解
2017/09/25 Javascript
AngularJS对动态增加的DOM实现ng-keyup事件示例
2018/03/12 Javascript
VUE2.0+ElementUI2.0表格el-table循环动态列渲染的写法详解
2018/11/30 Javascript
js中apply和call的理解与使用方法
2019/11/27 Javascript
微信小程序使用GoEasy实现websocket实时通讯
2020/05/19 Javascript
[01:00:59]VP VS VG Supermajor小组赛胜者组第二轮 BO3第二场 6.2
2018/06/03 DOTA
Django框架中方法的访问和查找
2015/07/15 Python
Python中装饰器学习总结
2018/02/10 Python
Python提取转移文件夹内所有.jpg文件并查看每一帧的方法
2019/06/27 Python
解决Mac下使用python的坑
2019/08/13 Python
Python调用scp向服务器上传文件示例
2019/12/22 Python
快速创建python 虚拟环境
2020/11/28 Python
HTML5 Web Database 数据库的SQL语句的使用方法
2012/12/09 HTML / CSS
Lookfantastic法国官网:英国知名美妆购物网站
2017/10/28 全球购物
C++:局部变量能否和全局变量重名
2014/03/03 面试题
中科前程Java笔试题
2016/11/20 面试题
读书活动实施方案
2014/03/10 职场文书
制冷与空调专业毕业生推荐信
2014/07/07 职场文书
党员创先争优心得体会
2014/09/11 职场文书
如何用python识别滑块验证码中的缺口
2021/04/01 Python
pandas中DataFrame数据合并连接(merge、join、concat)
2021/05/30 Python