python中wraps是什么意思_python 理解functools.wraps

先复习下装饰器

# coding=utf-8

def logged(func):

def with_logging(*args, **kwargs):

"""

哈哈哈,这里是with_logging

:param args:

:param kwargs:

:return:

"""

print func.__name__, " was called..."

return func(*args, **kwargs)

return with_logging

@logged

def f(x):

"""

哈哈,这是f

:param x:

:return:

"""

return x + x * x

print f.__name__

print f.__doc__

打印结果是:

(venv) ➜ myApp git:(v1.6_dev) ✗ python 1.py

with_logging

哈哈哈,这里是with_logging

:param args:

:param kwargs:

:return:

理论上这是不对的,因为函数f的信息已经获取不到了。。都被with_logging取代了。

解决方案:

# coding=utf-8

import functools

def logged(func):

@functools.wraps(func)

def with_logging(*args, **kwargs):

"""

哈哈哈,这里是with_logging

:param args:

:param kwargs:

:return:

"""

print func.__name__, " was called..."

return func(*args, **kwargs)

return with_logging

@logged

def f(x):

"""

哈哈,这是f

:param x:

:return:

"""

return x + x * x

print f.__name__

print f.__doc__

打印结果是:

(venv) ➜ myApp git:(v1.6_dev) ✗ python 1.py

f

哈哈,这是f

:param x:

:return:

以上是别的教程写的解决方案,突然对这个functools.wraps()有点兴趣,它到底是如何做到的呢?

functools.warp方法就是把被wrapped的函数的属性传递给wrapper的函数。

WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')

WRAPPER_UPDATES = ('__dict__',)

def update_wrapper(wrapper,

wrapped,

assigned = WRAPPER_ASSIGNMENTS,

updated = WRAPPER_UPDATES):

"""Update a wrapper function to look like the wrapped function

wrapper is the function to be updated

wrapped is the original function

assigned is a tuple naming the attributes assigned directly

from the wrapped function to the wrapper function (defaults to

functools.WRAPPER_ASSIGNMENTS)

updated is a tuple naming the attributes of the wrapper that

are updated with the corresponding attribute from the wrapped

function (defaults to functools.WRAPPER_UPDATES)

"""

for attr in assigned:

setattr(wrapper, attr, getattr(wrapped, attr))

for attr in updated:

getattr(wrapper, attr).update(getattr(wrapped, attr, {}))

# Return the wrapper so this can be used as a decorator via partial()

return wrapper

def wraps(wrapped,

assigned = WRAPPER_ASSIGNMENTS,

updated = WRAPPER_UPDATES):

"""Decorator factory to apply update_wrapper() to a wrapper function

Returns a decorator that invokes update_wrapper() with the decorated

function as the wrapper argument and the arguments to wraps() as the

remaining arguments. Default arguments are as for update_wrapper().

This is a convenience function to simplify applying partial() to

update_wrapper().

"""

return partial(update_wrapper, wrapped=wrapped,

assigned=assigned, updated=updated)

这个乍一看不是很理解,这个怎么和普通的装饰器不大一样呀。普通的长得像:

def out_wrapper(func):

def in_wrapper(*args, **kwargs):

print ‘in_wrapper’

return func(*args, **kwargs)

return in_wrapper

不过剥丝抽茧,先去除注释:

WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')

WRAPPER_UPDATES = ('__dict__',)

def update_wrapper(wrapper, wrapped, assigned = WRAPPER_ASSIGNMENTS, updated = WRAPPER_UPDATES):

for attr in assigned:

setattr(wrapper, attr, getattr(wrapped, attr))

for attr in updated:

getattr(wrapper, attr).update(getattr(wrapped, attr, {}))

return wrapper

def wraps(wrapped, assigned = WRAPPER_ASSIGNMENTS, updated = WRAPPER_UPDATES):

return partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated)

嗯,看起来简单清爽多了。考虑到偏函数,上面代码可以转成:

WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')

WRAPPER_UPDATES = ('__dict__',)

def update_wrapper(wrapper, wrapped, assigned = WRAPPER_ASSIGNMENTS, updated = WRAPPER_UPDATES):

for attr in assigned:

setattr(wrapper, attr, getattr(wrapped, attr))

for attr in updated:

getattr(wrapper, attr).update(getattr(wrapped, attr, {}))

return wrapper

def wraps(wrapped, assigned = WRAPPER_ASSIGNMENTS, updated = WRAPPER_UPDATES):

def in_wrapper(wrapper, wrapped=wrapped, assigned = WRAPPER_ASSIGNMENTS, updated = WRAPPER_UPDATES):

return update_wrapper(wrapper, wrapped=wrapped, assigned = WRAPPER_ASSIGNMENTS,updated = WRAPPER_UPDATES)

return in_wrapper

一般带参数的装饰器,是三层的,类似:

def wrapper(x):

def out_wrapper(func):

def in_wrapper(*args, **kwargs):

print ‘in_wrapper’

return func(*args, **kwargs)

return in_wrapper

return out_wrapper

虽然长得不一样,但思路就是返回一个能包装函数的函数变量,这帮作者写代码真是骚。

end...

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值