一些关于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的Django框架使用入门指引
Apr 15 Python
Swift 3.0在集合类数据结构上的一些新变化总结
Jul 11 Python
Python基于TCP实现会聊天的小机器人功能示例
Apr 09 Python
python爬取百度贴吧前1000页内容(requests库面向对象思想实现)
Aug 10 Python
python监控nginx端口和进程状态
Sep 06 Python
python 实现return返回多个值
Nov 19 Python
python获取引用对象的个数方式
Dec 20 Python
解决Pycharm中恢复被exclude的项目问题(pycharm source root)
Feb 14 Python
python GUI库图形界面开发之PyQt5信号与槽机制、自定义信号基础介绍
Feb 25 Python
Python-openpyxl表格读取写入的案例详解
Nov 02 Python
用gpu训练好的神经网络,用tensorflow-cpu跑出错的原因及解决方案
Mar 03 Python
提取视频中的音频 Python只需要三行代码!
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
LotusPhp笔记之:Cookie组件的使用详解
2013/05/06 PHP
关于PHP虚拟主机概念及如何选择稳定的PHP虚拟主机
2018/11/20 PHP
PHP xpath提取网页数据内容代码解析
2020/07/16 PHP
一个页面元素appendchild追加到另一个页面元素的问题
2013/01/27 Javascript
jquery实现弹出窗口效果的实例代码
2013/11/28 Javascript
Javascript中arguments和arguments.callee的区别浅析
2015/04/24 Javascript
浅析javascript的return语句
2015/12/15 Javascript
获取阴历(农历)和当前日期的js代码
2016/02/15 Javascript
jQuery数组处理函数整理
2016/08/03 Javascript
Angularjs实现分页和分页算法的示例代码
2016/12/23 Javascript
Bootstrap源码学习笔记之bootstrap进度条
2016/12/24 Javascript
Bootstrap轮播图学习使用
2017/02/10 Javascript
websocket+node.js实现实时聊天系统问题咨询
2017/05/17 Javascript
react.js使用webpack搭配环境的入门教程
2017/08/14 Javascript
详解webpack4升级指南以及从webpack3.x迁移
2018/06/12 Javascript
vue页面切换过渡transition效果
2018/10/08 Javascript
解决layui 三级联动下拉框更新时回显的问题
2019/09/03 Javascript
vue vant Area组件使用详解
2019/12/09 Javascript
vue select 获取value和lable操作
2020/08/28 Javascript
jquery实现点击左右按钮切换图片
2021/01/27 jQuery
Python+MongoDB自增键值的简单实现
2016/11/04 Python
Python简单I/O操作示例
2019/03/18 Python
对tensorflow中的strides参数使用详解
2020/01/04 Python
快速解决jupyter启动卡死的问题
2020/04/10 Python
pycharm 使用anaconda为默认环境的操作
2021/02/05 Python
HTML5之tabindex属性全面解析
2016/07/07 HTML / CSS
英国灯具和灯泡网上商店:Lights.co.uk
2018/02/02 全球购物
Baracuta官方网站:Harrington夹克,G9,G4,G10等
2018/03/06 全球购物
澳大利亚购买最佳炊具品牌网站:Cookware Brands
2019/02/16 全球购物
早会主持词
2014/03/17 职场文书
水利水电建筑施工应届生求职信
2014/07/04 职场文书
纪律教育学习月活动总结
2014/08/27 职场文书
2014年学生会部门工作总结
2014/11/07 职场文书
无工作证明怎么写
2015/06/15 职场文书
班级联欢会主持词
2015/07/03 职场文书
vue判断按钮是否可以点击
2022/04/09 Vue.js