考察上一节的 @log 装饰器:

def log(f):
def fn(x):
print 'call ' + f.__name__ + '()...'
return f(x)
return fn

发现对于被装饰的函数,log打印的语句是不能变的(除了函数名)。

如果有的函数非常重要,希望打印出'[INFO] call xxx()...',有的函数不太重要,希望打印出'[DEBUG] call xxx()...',这时,log函数本身就需要传入'INFO'或'DEBUG'这样的参数,类似这样:

@log('DEBUG')
def my_func():
pass

把上面的定义翻译成高阶函数的调用,就是:

my_func = log('DEBUG')(my_func)

上面的语句看上去还是比较绕,再展开一下:

log_decorator = log('DEBUG')
my_func = log_decorator(my_func)

上面的语句又相当于:

log_decorator = log('DEBUG')
@log_decorator
def my_func():
pass

所以,带参数的log函数首先返回一个decorator函数,再让这个decorator函数接收my_func并返回新函数:

def log(prefix):
def log_decorator(f):
def wrapper(*args, **kw):
print '[%s] %s()...' % (prefix, f.__name__)
return f(*args, **kw)
return wrapper
return log_decorator @log('DEBUG')
def test():
pass
print test()

执行结果:

[DEBUG] test()...
None

对于这种3层嵌套的decorator定义,你可以先把它拆开:

# 标准decorator:
def log_decorator(f):
def wrapper(*args, **kw):
print '[%s] %s()...' % (prefix, f.__name__)
return f(*args, **kw)
return wrapper
return log_decorator # 返回decorator:
def log(prefix):
return log_decorator(f)

拆开以后会发现,调用会失败,因为在3层嵌套的decorator定义中,最内层的wrapper引用了最外层的参数prefix,所以,把一个闭包拆成普通的函数调用会比较困难。不支持闭包的编程语言要实现同样的功能就需要更多的代码。

python中编写带参数decorator的更多相关文章

  1. python中编写无参数decorator

    Python的 decorator 本质上就是一个高阶函数,它接收一个函数作为参数,然后,返回一个新函数. 使用 decorator 用Python提供的 @ 语法,这样可以避免手动编写 f = de ...

  2. PYTHON 中 SQL 带参数

    使用 PYTHON 的字符串填充方式 import mysql.connector sql = 'select \* from school.student where age > {age} ...

  3. 编写带参数decorator

    无参的@log装饰器: def log(f): def fn(x): print 'call ' + f.__name__ + '()...' return f(x) return fn 发现对于被装 ...

  4. python中的装饰器decorator

    python中的装饰器 装饰器是为了解决以下描述的问题而产生的方法 我们在已有的函数代码的基础上,想要动态的为这个函数增加功能而又不改变原函数的代码 例如有三个函数: def f1(x): retur ...

  5. python 中函数的参数

    一.python中的函数参数形式 python中函数一般有四种表现形式: 1.def function(arg1, arg2, arg3...) 这种是python中最常见的一中函数参数定义形式,函数 ...

  6. python中的魔法参数:*args和**kwargs

    python中的魔法参数:*args和**kwargs def foo(*args, **kwargs):print 'args = ', argsprint 'kwargs = ', kwargsp ...

  7. Python进阶(七)----带参数的装饰器,多个装饰器修饰同一个函数和递归简单案例(斐波那契数列)

    Python进阶(七)----带参数的装饰器,多个装饰器修饰同一个函数和递归简单案例(斐波那契数列) 一丶带参数的装饰器 def wrapper_out(pt): def wrapper(func): ...

  8. 深入理解python中函数传递参数是值传递还是引用传递

    深入理解python中函数传递参数是值传递还是引用传递 目前网络上大部分博客的结论都是这样的: Python不允许程序员选择采用传值还是传 引用.Python参数传递采用的肯定是"传对象引用 ...

  9. Python中函数传递参数有四种形式

    Python中函数传递参数有四种形式 fun1(a,b,c) fun2(a=1,b=2,c=3) fun3(*args) fun4(**kargs) 四种中最常见是前两种,基本上一般点的教程都会涉及, ...

随机推荐

  1. android Splashy Flash小游戏

    今年刚開始学习android,自己在寝室捎带学习了下做APP,因为是刚開始学习,这个游戏仅仅注重了游戏的实现,实现了大概功能后.也没有实现游戏的细节,像分数图片的显示等.也没有注意代码的结构.一个字就 ...

  2. 【转】 VC++ 关闭程序后任务管理器进程中进程仍然存在的解决方法

    转载出处:http://blog.csdn.net/zac_sian/article/details/50809084 可以从以下两个方面进行查找! 1.程序开启了进程,进程中使用了while(1), ...

  3. ios . -- UICollectionView --cell 自适应

    #pragma mark — 视图控制器中使用:(关键) layout.estimatedItemSize = CGSizeMake(WIDTH, ); // layout约束这边必须要用estima ...

  4. python:编写行政区域三级菜单(day 1)

    地区分三层结构例如: 大中华地区一级划分: 华东 华中 华北 西南 特别行政区 华南 ------------------------------------------------- 请输入你要查看 ...

  5. 大话DFT频谱分析(并不是我的话)

    有限长信号DFT结果的频谱泄露 提出问题 依照我们在"信号与系统"这门课建立的印象,不管如何频率的连续正弦信号,其频谱应当是两根笔直的谱线(含负频率) 但是,当我们把一段正弦信号採 ...

  6. jmeter 参数值写入到指定的文件中[如获取token写入某文件为免登录备用]

    1.编写java 类AppendFile ,代码如下 import java.io.File;import java.io.FileWriter;import java.io.IOException; ...

  7. TP数据删除

    [数据删除及执行原生sql语句] delete()  返回受影响的记录条数 $goods -> delete(30);   删除主键值等于30的记录信息 $goods -> delete( ...

  8. COGS 693. [SDOI2005]Antiprime数 唯一分解定理逆用

    693. Antiprime数 ★★   输入文件:antip.in   输出文件:antip.out   简单对比 时间限制:1 s   内存限制:128 MB 如果一个自然数n(n>=1), ...

  9. POJ 1789 Truck History【最小生成树简单应用】

    链接: http://poj.org/problem?id=1789 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=22010#probl ...

  10. VSpy之C Code Interface的使用

    Spy3 要运行 CCodeInterface 功能,需要安装运行环境,建议安装 Visual Studio2003,2005,2008,2010 或更新的版本.当然也可以安装 VC express ...