参考链接:https://stackoverflow.com/questions/739654/how-to-make-a-chain-of-function-decorators

1. 函数对象

  • 能够赋值给其他变量
  • 能够在另外函数内定义
  • 能够作为参数进行传递
  • 能够作为函数的返回值
def firstLevel(f_arg):  # 作为参数,可以赋值
def tmp_func(*args, **kwargs): # 可以在另外函数内定义
# do something ...
ret = f_arg(*args, **kwargs)
# do something ...
return ret
return tmp_func # 作为函数的返回值 # 1. 原始方法
def func(*args, **kwargs):
print("In func")
func = firstLevel(func) # 2. 装饰器方法
@firstLevel
def func(*args, **kwargs):
print("In func") # 使用
func()

2. 多层装饰器

可以对函数进行一层又一层的包装,使用多层装饰器即可

def firstLevel(f_arg):
def tmp_func(*args, **kwargs):
print("----s.firstLevel----")
ret = f_arg(*args, **kwargs)
print("----e.firstLevel----")
return ret
return tmp_func def secondLevel(f_arg):
def tmp_func(*args, **kwargs):
print("----s.secondLevel----")
ret = f_arg(*args, **kwargs)
print("----e.secondLevel----")
return ret
return tmp_func #1. 原始方法
def func(*args, **kwargs):
print("In func")
func = firstLevel(secondLevel(func))
func() # 2. 装饰器方法
@firstLevel
@secondLevel
def func(*args, **kwargs):
print("In func")
func()

@firstLevel 语法,

这个后面看似隐藏了一对(),用来将下面的代码作为装饰器函数返回的内部函数的参数进行传递,当明确指定()的时候,则是给装饰器函数传递参数,

3. 装饰器接收参数

@firstLevel 语法,告诉我们这个函数接收的参数是一个函数对象,内部返回的是一个函数(firstLevel就是函数名,使用@标记告诉我们的)

@firstLevel(arg1, arg2, ...) 语法,告诉我们这个firstLevel(arg1, arg2, ...) 函数接收参数,返回的也是一个函数,返回的函数比如叫 retLevel,则将转化为: @retLevel 语法,retLevel 语法就跟上面的语法一样,告诉我们返回的 retLevel 接收的参数是一个函数对象,内部同样返回了一个函数 (retLevel 就是中间函数名,使用@标记告诉我们的)

def firstLevel(arg1, arg2):
# do something ...
print(arg1, arg2)
# 使用参数做一些事情(这是函数传递参数的目的)
def tmpRetLevel(f_arg):
def tmp_func(*args, **kwargs):
# do something ...
ret = f_arg(*args, **kwargs)
# do something ...
return ret
return tmp_func return tmpRetLevel # 1. 原始方法
def func(*args, **kwargs):
print("In func") retLevel = firstLevel('', '')
func = retLevel(func)
func('', '') # 2. 装饰器方法
@firstLevel('', '')
def func(*args, **kwargs):
print("In func") func('', '')

4. functools实现装饰器

上面的返回后的函数,打印一些内部变量比如:func.__doc__, __name__ 将变为 内部函数的 __doc__,__name__ 描述信息,functools.wraps将解决这样的问题,wraps()函数本身就是一个装饰器。

import functools

def firstLevel(f_arg):
@functools.wraps(f_arg):
def tmpFunc(*args, **kwargs):
# do something ...
ret = f_arg(*args, **kwargs)
# do something ...
return ret
return tmpFunc @firstLevel
def func(*args, **kwargs):
print("In func") print(func.__name__) # 输出:func

4. 使用场景

  • 装饰外部提供的库
  • 避免大量重复代码的编写
  • 比如:Django对视图的权限控制,Twisted将函数修改为异步调用

[TimLinux] Python 再谈装饰器的更多相关文章

  1. python再议装饰器

    装饰器实质还是一个函数,是对其他函数进行装饰的函数.装饰器函数接受被装饰函数的函数名,返回被装饰函数的函数名.对一个函数进行装饰有两个原则:一是不能修改被装饰函数的源代码:二是被装饰函数的调用方式不可 ...

  2. [TimLinux] Python 再谈元类 metaclass

    本博文通过对以下链接进行理解后,编写. https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python 1. 类 类 ...

  3. 浅显易懂的谈一谈python中的装饰器!!

    hello大家好~~我是稀里糊涂林老冷,一天天稀里糊涂的. 前一段时间学习了装饰器,觉着这东西好高大上哇靠!!哈哈,一定要总结一下,方便以后自己查阅,也希望帮助其他伙伴们共同进步! 装饰器: 大家可以 ...

  4. python之路——装饰器函数

    阅读目录 楔子 装饰器的形成过程 开放封闭原则 谈装饰器主要功能和装饰器固定结构 带参数的装饰器 多个装饰器装饰一个函数 返回顶部 楔子 作为一个会写函数的python开发,我们从今天开始要去公司上班 ...

  5. python之路---装饰器函数

    阅读目录 楔子 装饰器的形成过程 开放封闭原则 谈装饰器主要功能和装饰器固定结构 带参数的装饰器 多个装饰器装饰一个函数 返回顶部 楔子 作为一个会写函数的python开发,我们从今天开始要去公司上班 ...

  6. python高级之装饰器

    python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函数的定义: 满足下面两个条件之 ...

  7. Day04 - Python 迭代器、装饰器、软件开发规范

    1. 列表生成式 实现对列表中每个数值都加一 第一种,使用for循环,取列表中的值,值加一后,添加到一空列表中,并将新列表赋值给原列表 >>> a = [0, 1, 2, 3, 4, ...

  8. Noah的学习笔记之Python篇:装饰器

    Noah的学习笔记之Python篇: 1.装饰器 2.函数“可变长参数” 3.命令行解析 注:本文全原创,作者:Noah Zhang  (http://www.cnblogs.com/noahzn/) ...

  9. 第二篇:python高级之装饰器

    python高级之装饰器   python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函 ...

随机推荐

  1. Ansible之系列命令详解

    ansible系列命令有:ansible.ansible-doc.ansible-playbook.ansible-vault.ansible-console.ansible-galaxy.ansib ...

  2. Geometry 判断几何是否被另一个几何/线段分割成多段

    如下图,如何判断几何多边形A被多边形B,切割为多段几何? 几何A被几何B切割 1. 获取几何A与几何B的交集C var intersectGeometry = new CombinedGeometry ...

  3. 第一篇:jdk8下载和idea导入,java源码结构

    一.下载和导入 下载和导入到idea,完全参考文章:https://blog.csdn.net/zhanglong_4444/article/details/88967300 照做即可,详解简单到位. ...

  4. nyoj 513-A+B Problem IV (java BigDecimal, stripTrailingZeros, toPlainString)

    513-A+B Problem IV 内存限制:64MB 时间限制:1000ms 特判: No 通过数:1 提交数:2 难度:3 题目描述: acmj最近发现在使用计算器计算高精度的大数加法时很不方便 ...

  5. 基于 cobbler 实现自动安装 linux 系统

    使用 cobbler 实现自动安装 centos 6.7系统 1.yum install cobbler -y 安装 cobbler ,有依赖关系,会自动把 TFTP .HTTP 服务安装上:cobb ...

  6. apple平台下的objc的GCD,多线程编程就是优雅自然。

    在apple的操作系统平台里,GCD使得多线程编程是那么的优雅自然.在传统的多线程编程中,首先要写线程处理循环:之后还有事件队列,消息队列:还要在线程循环中分离事件解释消息,分派处理:还要考虑线程间是 ...

  7. MySQL 备份数据那点事

    mysqldump 什么是 mysqldump ? mysqldump 是 MySQL 用于执行逻辑备份的一款工具,可以根据原始数据库对象以及表的定义和数据来生成一系列可以被执行的 SQL 语句. 通 ...

  8. proxy protocol

    Proxy protocol 是haproxy 作者开发和设计的一个inernet 协议, 用于获取客户端的IP地址. 在使用7层代理是可以向http协议添加X-Forword-For来实现,而4层协 ...

  9. ASP.NET Aries 高级开发教程:如何写WebAPI接口

    前提: 最近,有不少同学又问到,Aries里如何提供WebAPI接口? 针对这个问题,今天给顺路写个教程,其实呢,很简单的. 方式一:直接用WebService提供接口. 用这种方式,直接添加接口就可 ...

  10. 新闻实时分析系统 Spark Streaming实时数据分析

    1.Spark Streaming功能介绍1)定义Spark Streaming is an extension of the core Spark API that enables scalable ...