一些关于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写的一个wordpress的采集程序
Feb 27 Python
Python装饰器用法示例小结
Feb 11 Python
python获取本机所有IP地址的方法
Dec 26 Python
python3中替换python2中cmp函数的实现
Aug 20 Python
基于Python中的yield表达式介绍
Nov 19 Python
python的range和linspace使用详解
Nov 27 Python
pytorch模型预测结果与ndarray互转方式
Jan 15 Python
使用Keras预训练模型ResNet50进行图像分类方式
May 23 Python
Python读取二进制文件代码方法解析
Jun 22 Python
Python制作数据预测集成工具(值得收藏)
Aug 21 Python
简单的命令查看安装的python版本号
Aug 28 Python
利用python实现后端写网页(flask框架)
Feb 28 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
php常量详细解析
2015/10/27 PHP
php制作的简单验证码识别代码
2016/01/26 PHP
phpstudy2020搭建站点的实现示例
2020/10/30 PHP
JavaScript null和undefined区别分析
2009/10/14 Javascript
JavaScript OOP类与继承
2009/11/15 Javascript
JQuery 1.4 中的Ajax问题
2010/01/23 Javascript
jQuery prev ~ siblings选择器使用介绍
2013/08/09 Javascript
自己写的Javascript计算时间差函数
2013/10/28 Javascript
各浏览器对document.getElementById等方法的实现差异解析
2013/12/05 Javascript
Javascript中call的两种用法实例
2013/12/13 Javascript
从数据库读取数据后将其输出成html标签的三种方法
2014/10/13 Javascript
node.js使用npm 安装插件时提示install Error: ENOENT报错的解决方法
2014/11/20 Javascript
JavaScript检查子字符串是否在字符串中的方法
2016/02/03 Javascript
关于动态执行代码(js的Eval)实例详解
2016/08/15 Javascript
使用JavaScript为一张图片设置备选路径的方法
2017/01/04 Javascript
微信小程序开发之相册选择和拍照详解及实例代码
2017/02/22 Javascript
微信小程序 判断手机号的实现代码
2017/04/19 Javascript
移动端web滚动分页的实现方法
2017/05/05 Javascript
详解vue模拟加载更多功能(数据追加)
2017/06/23 Javascript
JavaScript之事件委托实例(附原生js和jQuery代码)
2017/07/22 jQuery
JavaScript数组的5种迭代方法
2017/09/29 Javascript
node.js+express+mySQL+ejs+bootstrop实现网站登录注册功能
2018/01/12 Javascript
vue2.0实现移动端的输入框实时检索更新列表功能
2018/05/08 Javascript
解决vue-cli脚手架打包后vendor文件过大的问题
2018/09/27 Javascript
原生JavaScript实现幻灯片效果
2021/02/19 Javascript
举例讲解Python的Tornado框架实现数据可视化的教程
2015/05/02 Python
itchat和matplotlib的结合使用爬取微信信息的实例
2017/08/25 Python
Centos7 Python3下安装scrapy的详细步骤
2018/03/15 Python
Window10+Python3.5安装opencv的教程推荐
2018/04/02 Python
详解python selenium 爬取网易云音乐歌单名
2019/03/28 Python
Python面向对象魔法方法和单例模块代码实例
2020/03/25 Python
Django数据结果集序列化并展示实现过程
2020/04/22 Python
django rest framework serializers序列化实例
2020/05/13 Python
在CentOS7下安装Python3教程解析
2020/07/09 Python
Python2手动安装更新pip过程实例解析
2020/07/16 Python
Java中生成微信小程序太阳码的实现方案
2022/06/01 Java/Android