python中wraps_python 装饰器及标准库functools中的wraps

最近在看 flask的视图装饰器 时,忽然想起预(复)习一下python的装饰器.

这里有一篇比较好的讲解装饰器的书写的 Python装饰器学习(九步入门) .

这里不单独记录装饰器的书写格式了,重点是工作流程.

首先常见的 装饰器 格式就是通过@语法糖,简便的写法,让流程有些不太清楚.

装饰器不带参数的情况下:

def deco(func):

def _deco():

print("before myfunc() called.")

func()

print("  after myfunc() called.")

return _deco

@deco

def myfunc():

print(" myfunc() called.")

myfunc()

运行结果:

before myfunc() called.

myfunc() called.

after myfunc() called.

myfunc() called.

这个@语法糖的作用是:

def myfunc():

print(" myfunc() called.")

myfunc = deco(myfunc)

也就是现在的myfunc不再是一开始定义的那个了,而变成了

def _deco():

print("before myfunc() called.")

func()

print("  after myfunc() called.")

这一点可以通过

print myfunc.__name__

而复杂一点的,装饰器带参数的,如:

def deco(arg="haha"):

def _deco(func):

def __deco():

print("before %s called [%s]." % (func.__name__, arg))

func()

print("  after %s called [%s]." % (func.__name__, arg))

return __deco

return _deco

@deco()#注意有括号

def myfunc():

print(" myfunc() called.")

@deco("haha1")

def myfunc1():

print(" myfunc() called.")

myfunc()

myfunc1()

实际的操作是,先把装饰进行了运算,即函数deco先被调用

等效于:

def _deco(func):

def __deco():

print("before %s called [%s]." % (func.__name__, "haha"))# arg ==> "haha"

func()

print("  after %s called [%s]." % (func.__name__, "haha"))# arg ==> "haha"

return __deco

@d_deco#注意没有括号,第一处

def myfunc():

print(" myfunc() called.")

@_deco#这也没括号,第二处

def myfunc1():

print(" myfunc1() called.")

myfunc()

myfunc1()

而参数arg 使用的是默认的"haha

更直观的表达方式就是:

def deco(arg="haha"):

def _deco(func):

def __deco():

print("before %s called [%s]." % (func.__name__, arg))

func()

print("  after %s called [%s]." % (func.__name__, arg))

return __deco

return _deco

def myfunc():

print(" myfunc() called.")

def myfunc1():

print(" myfunc() called.")

myfunc = deco()(myfunc)

myfunc1 = deco("haha1")(myfunc1)

这时再来看标准库functools中的wraps的使用,比如官网例子:

from functools import wraps

def my_decorator(f):

@wraps(f)

def wrapper(*args, **kwds):

print 'Calling decorated function'

return f(*args, **kwds)

return wrapper

@my_decorator

def example():

"""Docstring"""

print 'Called example function'

example()

print example.__name__

print example.__doc__

过程就是

def my_decorator(f):

def wrapper(*args, **kwds):

print 'Calling decorated function'

return f(*args, **kwds)

wrapper.__name__ = f.__name__

wrapper.__doc__  = f.__doc__

return wrapper

example = my_decorator(example)

这样就保留了原函数名称属性和doc,

标准库中函数wraps,可以这样理解:

def wraps(f):

def _f(*args,**kwargs):

f(*args,**kwargs)

_f.__name__ = f.__name

_f.__doc__  = f.__doc__

return _f

上面的wraps流程可以看出,如果直接使用wraps简直就是f = f(其实不能直接使用),所以一般都是如实例这样包藏在一个装饰器函数内部.

来源:oschina

链接:https://my.oschina.net/u/1755923/blog/495293

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值