笔记-python-functool-@wraps

1.      wraps

经常看到@wraps装饰器,查阅文档学习一下

在了解它之前,先了解一下partial和updata_wrapper这两个前置技能,因为在wraps中用到了。

1.1.    partial

偏函数

源代码:

class partial:

"""New function with partial application of the given arguments

and keywords.

"""

__slots__ = "func", "args", "keywords", "__dict__", "__weakref__"

def __new__(*args, **keywords):

if not args:

raise TypeError("descriptor '__new__' of partial needs an argument")

if len(args) < 2:

raise TypeError("type 'partial' takes at least one argument")

cls, func, *args = args

if not callable(func):

raise TypeError("the first argument must be callable")

args = tuple(args)

if hasattr(func, "func"):

args = func.args + args

tmpkw = func.keywords.copy()

tmpkw.update(keywords)

keywords = tmpkw

del tmpkw

func = func.func

self = super(partial, cls).__new__(cls)

self.func = func

self.args = args

self.keywords = keywords

return self

def __call__(*args, **keywords):

if not args:

raise TypeError("descriptor '__call__' of partial needs an argument")

self, *args = args

newkeywords = self.keywords.copy()

newkeywords.update(keywords)

return self.func(*self.args, *args, **newkeywords)

重点关注构造方法和调用方法,可以看出整体的作用等效于构造一个新了函数,但新的函数包括了原函数的参数,多用于简化代码。

实现原理/过程:实际上返回的是一个partial实例(可调用),有三个重要属性,self.func指向传入函数,args和keywords为可变参数;
调用返回的partial对象实质上是执行func()

案例如下:

def u(a,b,*args):

pass

u1 = partial(u,4,5,7)

print('u: {1}{0}u1: {2}{0}u1.func: {3}{0}u1.args: {4}'.format('\n',u,u1,u1.func,u1.args))

输出:

u: <function u at 0x000000130F5FB378>
u1: functools.partial(<function u at 0x000000130F5FB378>, 4, 5, 7)
u1.func: <function u at 0x000000130F5FB378>
u1.args: (4, 5, 7)

>>>

1.2.    update_wrapper

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:

try:

value = getattr(wrapped, attr)

except AttributeError:

pass

else:

setattr(wrapper, attr, value)

for attr in updated:

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

# Issue #17482: set __wrapped__ last so we don't inadvertently copy it

# from the wrapped function when updating __dict__

wrapper.__wrapped__ = wrapped

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

return wrapper

简单来说,就是把wrapper的相关属性改成和wrapped相同的。返回wrapper

1.3.    wraps

回到wraps

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)

核心就一句,实际就是一个修饰器版的update_wrapper,将被修饰的函数(wrapped)

注意这里的写法,wrapped=wrapped,对偏函数而言,该参数写成关键字参数与写成位置参数-wrapped-所带来的结果不一样。

注意,下面这种写法会导致结果反转:

return partial(update_wrapper, wrapped,

assigned=assigned, updated=updated)

1.4.    总结

wraps装饰器的作用就是更改函数名称和属性。

当使用装饰器装饰一个函数时,函数本身就已经是一个新的函数;即函数名称或属性产生了变化。所以在装饰器的编写中建议加入wraps确保被装饰的函数不会因装饰器带来异常情况。

笔记-python-functool-@wraps的更多相关文章

  1. python functools.wraps functools.partial实例解析

    一:python functools.wraps 实例 1. 未使用wraps的实例 #!/usr/bin/env python # coding:utf-8 def logged(func): de ...

  2. functool.wraps and functools.partial

    functools.partial 通过包装手法,允许我们 "重新定义" 函数签名.  通常是将函数的部分参数给固定下来, 从而形成一个输入参数更少的新函数. functool.w ...

  3. 笔记-python操作mysql

    笔记-python操作mysql 1.      开始 1.1.    环境准备-mysql create database db_python; use db_python; create tabl ...

  4. 笔记-python异常信息输出

    笔记-python异常信息输出 1.      异常信息输出 python异常捕获使用try-except-else-finally语句: 在except 语句中可以使用except as e,然后通 ...

  5. 笔记-python -asynio

    笔记-python -asynio 1.      简介 asyncio是做什么的? asyncio is a library to write concurrent code using the a ...

  6. 笔记-python lib-pymongo

    笔记-python lib-pymongo 1.      开始 pymongo是python版的连接库,最新版为3.7.2. 文档地址:https://pypi.org/project/pymong ...

  7. 笔记-python tutorial-9.classes

    笔记-python tutorial-9.classes 1.      Classes 1.1.    scopes and namespaces namespace: A namespace is ...

  8. MongoDB学习笔记:Python 操作MongoDB

    MongoDB学习笔记:Python 操作MongoDB   Pymongo 安装 安装pymongopip install pymongoPyMongo是驱动程序,使python程序能够使用Mong ...

  9. 机器学习实战笔记(Python实现)-08-线性回归

    --------------------------------------------------------------------------------------- 本系列文章为<机器 ...

  10. 机器学习实战笔记(Python实现)-05-支持向量机(SVM)

    --------------------------------------------------------------------------------------- 本系列文章为<机器 ...

随机推荐

  1. [持续更新] Linux基础的重要命令

    命令总结:100个左右 mkdir 方法一 [root@localhost ~]# mkdir /test && ls -ld /test 方法二 [root@localhost ~] ...

  2. 移动端absolute元素居中

    <div class="db"> <div class="dm"></div> </div> .db{ widt ...

  3. (13)JavaScript之[HTML DOM元素][JS对象]

    元素 /** * HTML DOM 元素(节点)*/ //创建新的HTML元素 var para = document.createElement('p'); var node = document. ...

  4. 【Node.js】初识Node.js

    因组里项目需要,我和另外一名同事要学习Node.js.之前接触过Javascript,都是前台处理html时用到,现在要用Javascript做后端,学习Node.js,用一段时间专心学习一门新技术, ...

  5. Element-ui(el-table、el-pagination)实现表格分页

    HTML代码:(重点关注el-table中:data数据的绑定) el-pagination中: layout代表组件布局,子组件名用逗号分隔 属性: total代表总条目数 事件: current- ...

  6. 永恒之蓝EternalBlue复现

    0x01 漏洞原理:http://blogs.360.cn/blog/nsa-eternalblue-smb/ 目前已知受影响的 Windows 版本包括但不限于:Windows NT,Windows ...

  7. 关于硬盘分区使用exFat格式的优势及劣势(含摘抄)

    优势 可以设置最大32M的簇: 不记录日志. 劣势 无法使用windows的“文件共享”: 通过近期某个文件数量密级任务的测试发现,在大量文件的处理性能上,NTFS比exFAT文件系统的性能高出不少. ...

  8. C语言总结的知识点

    什么是有效数字? ------------------------- 数据类型 运算符: 函数: 程序结构: 存储结构 内存管理 关键字: ------------------------- C语言: ...

  9. Altium_Designer-PCB的覆铜步骤

    1.覆铜的意义     覆铜,就是将PCB上闲置的空间作为基准面,然后用固体铜填充,这些铜区又称为灌铜.敷铜的意义在于,减小地线阻抗,提高抗干扰能力:降低压降,提高电源效率:还有,与地线相连,减小环路 ...

  10. 【转载】#402 - Value Equality vs. Reference Equality

    When we normally think of "equality",we're thinking of value equality - the idea that the ...