一些关于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抓取京东图书评论数据
Aug 31 Python
Python程序中使用SQLAlchemy时出现乱码的解决方案
Apr 24 Python
Python实现监控程序执行时间并将其写入日志的方法
Jun 30 Python
Python中几种导入模块的方式总结
Apr 27 Python
python使用json序列化datetime类型实例解析
Feb 11 Python
Python使用APScheduler实现定时任务过程解析
Sep 11 Python
Python爬取知乎图片代码实现解析
Sep 17 Python
Python嵌套函数,作用域与偏函数用法实例分析
Dec 26 Python
Pycharm 2020最新永久激活码(附最新激活码和插件)
Sep 17 Python
Python run()函数和start()函数的比较和差别介绍
May 03 Python
详解基于python的图像Gabor变换及特征提取
Oct 26 Python
python 安全地删除列表元素的方法
Mar 16 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
使用无限生命期Session的方法
2006/10/09 PHP
php实现encode64编码类实例
2015/03/24 PHP
超清晰的document对象详解
2007/02/27 Javascript
js资料prototype 属性
2007/03/13 Javascript
使用EXT实现无刷新动态调用股票信息
2008/11/01 Javascript
基于jQuery的淡入淡出可自动切换的幻灯插件
2010/08/24 Javascript
用js小类库获取浏览器的高度和宽度信息
2012/01/15 Javascript
使用jquery mobile做幻灯播放效果实现步骤
2013/01/04 Javascript
JS和函数式语言的三特性
2014/03/05 Javascript
一个jquery实现的不错的多行文字图片滚动效果
2014/09/28 Javascript
js获取新浪天气接口的实现代码
2016/06/06 Javascript
vue-prop父组件向子组件进行传值的方法
2018/03/01 Javascript
JavaScript实现简单的隐藏式侧边栏功能示例
2018/08/31 Javascript
10个最受欢迎的 JavaScript框架(推荐)
2019/04/24 Javascript
Taro UI框架开发小程序实现左滑喜欢右滑不喜欢效果的示例代码
2020/05/18 Javascript
何时/使用 Vue3 render 函数的教程详解
2020/07/25 Javascript
Vue+Element ui 根据后台返回数据设置动态表头操作
2020/09/21 Javascript
[52:00]2018DOTA2亚洲邀请赛 4.1 小组赛 A组加赛 LGD vs Optic
2018/04/02 DOTA
[01:26]DOTA2荣耀之路2:iG,China
2018/05/24 DOTA
Python isinstance判断对象类型
2008/09/06 Python
在Python中使用判断语句和循环的教程
2015/04/25 Python
Python2.7简单连接与操作MySQL的方法
2016/04/27 Python
利用Python自动监控网站并发送邮件告警的方法
2016/08/24 Python
详解Python静态网页爬取获取高清壁纸
2019/04/23 Python
python requests证书问题解决
2019/09/05 Python
python 已知平行四边形三个点,求第四个点的案例
2020/04/12 Python
详解matplotlib中pyplot和面向对象两种绘图模式之间的关系
2021/01/22 Python
CSS3+Sprite实现僵尸行走动画特效源码
2016/01/27 HTML / CSS
HTML5地理定位_动力节点Java学院整理
2017/07/12 HTML / CSS
德国高尔夫商店:Par71.de
2020/11/29 全球购物
Android面试题及答案
2015/09/04 面试题
护理学中专毕业生求职信
2013/11/11 职场文书
幼儿园教师请假制度
2014/01/16 职场文书
支教自我鉴定
2014/01/18 职场文书
Python合并pdf文件的工具
2021/07/01 Python
Spring Boot项目如何优雅实现Excel导入与导出功能
2022/06/10 Java/Android