Python完善decorator

@decorator可以动态实现函数功能的增加,但是,经过@decorator“改造”后的函数,和原函数相比,除了功能多一点外,有没有其它不同的地方?

在没有decorator的情况下,打印函数名:

def f1(x):
    pass
print f1.__name__

输出: f1

有decorator的情况下,再打印函数名:

def log(f):
    def wrapper(*args, **kw):
        print ‘call...‘
        return f(*args, **kw)
    return wrapper
@log
def f2(x):
    pass
print f2.__name__

输出: wrapper

可见,由于decorator返回的新函数函数名已经不是‘f2‘,而是@log内部定义的‘wrapper‘。这对于那些依赖函数名的代码就会失效。decorator还改变了函数的__doc__等其它属性。如果要让调用者看不出一个函数经过了@decorator的“改造”,就需要把原函数的一些属性复制到新函数中:

def log(f):
    def wrapper(*args, **kw):
        print ‘call...‘
        return f(*args, **kw)
    wrapper.__name__ = f.__name__
    wrapper.__doc__ = f.__doc__
    return wrapper

这样写decorator很不方便,因为我们也很难把原函数的所有必要属性都一个一个复制到新函数上,所以Python内置的functools可以用来自动化完成这个“复制”的任务:

import functools
def log(f):
    @functools.wraps(f)
    def wrapper(*args, **kw):
        print ‘call...‘
        return f(*args, **kw)
    return wrapper

最后需要指出,由于我们把原函数签名改成了(*args, **kw),因此,无法获得原函数的原始参数信息。即便我们采用固定参数来装饰只有一个参数的函数:

def log(f):
    @functools.wraps(f)
    def wrapper(x):
        print ‘call...‘
        return f(x)
    return wrapper

也可能改变原函数的参数名,因为新函数的参数名始终是 ‘x‘,原函数定义的参数名不一定叫 ‘x‘。

任务

请思考带参数的@decorator,@functools.wraps应该放置在哪:

def performance(unit):
    def perf_decorator(f):
        def wrapper(*args, **kw):
            ???
        return wrapper
    return perf_decorator
?不会了怎么办

注意@functools.wraps应该作用在返回的新函数上。

参考代码:

import time, functools
def performance(unit):
    def perf_decorator(f):
        @functools.wraps(f)
        def wrapper(*args, **kw):
            t1 = time.time()
            r = f(*args, **kw)
            t2 = time.time()
            t = (t2 - t1) * 1000 if unit==‘ms‘ else (t2 - t1)
            print ‘call %s() in %f %s‘ % (f.__name__, t, unit)
            return r
        return wrapper
    return perf_decorator

@performance(‘ms‘)
def factorial(n):
    return reduce(lambda x,y: x*y, range(1, n+1))
print factorial.__name__

时间: 2024-10-29 19:10:11

Python完善decorator的相关文章

Python 之 decorator装饰器

最近看到 廖雪峰 的Python教程,对于学习Python的人来说,这可谓是一大福音,没有冗长的废话,只有最通俗简短的语言,以及最清晰的例子讲解. 下面是我对 装饰器 这一小节的总结, 以及自己的理解. 注:[本文中的代码参考上述教程] 很多时候我会把Python的很多语法与C++相融合,在C++中,函数的名称即为函数的地址,我们可以通过定义成为"函数指针"的变量,并且将函数名称赋值给该变量,那么我们在调用函数的时候,就可以直接使用该变量调用函数. 例如下面的C++的代码就是一个简单的

转载:唐磊的个人博客《python中decorator详解》【转注:深入浅出清晰明了】

转载请注明来源:唐磊的个人博客<python中decorator详解> 前面写python的AOP解决方案时提到了decorator,这篇文章就详细的来整理下python的装饰器--decorator. python中的函数即objects 一步一步来,先了解下python中的函数. def shout(word='hello,world'):     return word.capitalize() + '!'print shout()#输出:Hello,world!#跟其他对象一样,你同样

python中完善decorator

@decorator可以动态实现函数功能的增加,但是,经过@decorator"改造"后的函数,和原函数相比,除了功能多一点外,有没有其它不同的地方? 在没有decorator的情况下,打印函数名: def f1(x): pass print f1.__name__ 输出: f1 有decorator的情况下,再打印函数名: def log(f): def wrapper(*args, **kw): print 'call...' return f(*args, **kw) retur

Python 之 decorator 装饰器

python 在语法上对装饰模式进行了支持. 一.问题 有如下的一个函数, def sum(x, y):     print "x+y:", x+y 我们需要在每次调用 sum 函数的时候打印日志,但是我们并不希望修改sum函数. 二.解决方案 Solution 1: 最 brute-force 的方法,定义一个包裹函数, 在这个包裹函数的内部调用sum 函数(包裹函数和 sum 函数最好具有相同的参数,和返回类型) def wrapper1(x, y):     print &quo

python中decorator

先讲一下python中的@符号 看下面代码 @f @f2 def fun(args, args2, args3, args4, ……): pass 上面代码相当于 def fun(args, args2, args3, args4, ……): pass fun = fun(f2(fun))

python:practice decorator calaulate_time

from functools import reduce import time def  factorial_array(n) number=reduce(lambda x,y:x*y,range(1,n+1)) return number print( factorial_array(101) def calaulate_time(func): start_time=time.time() func() end_time=time.time() return end_time-start_t

python 装饰器学习(decorator)

最近看到有个装饰器的例子,没看懂, #!/usr/bin/python class decorator(object): def __init__(self,f): print "initial decorator" f() def __call__(self): print "call decorator" @decorator def fun(): print "in the fun" print "after " fun

python 语法之 decorator

装饰器 decorator 或者称为包装器,是对函数的一种包装. 它能使函数的功能得到扩充,而同时不用修改函数本身的代码. 它能够增加函数执行前.执行后的行为,而不需对调用函数的代码做任何改变. 下面用一个简单的例子介绍装饰器: 1 # 函数hello,输出 hello + name 的字符串 2 def hello(name): 3 return 'hello ' + name 下面,我们希望在每一个调用 hello 函数的时候,将输出的字符串用 <tag>包住 比如:hello john

python 中的decorator

python 中decorator的作用就是一个包装的作用,所谓包装指在执行真正的函数之前或者之后,我们可以有一些额外的发挥余地. decorator形式如下 def dec(arg1): print("dec",arg1) def func_replace(func): print("func_replace",func) def call_real_func(*args,**kwargs): print("call_real_func") f