笔记-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. Developer - 如何自我保证Node.js模块质量

    组里正在做SaaS产品,其中一些模块(Module)是Node.js实现,这里我们主要使用Node.js实现Web Server来提供服务. 在做SaaS项目之前,组里的开发模式是传统的Deverlo ...

  2. struts2 中使用DMI(动态调用方法)方式配置action

    1.使用 "!"方式,即 action名称 ! 方法名称 struts.xml 配置 <package name="user" namespace=&qu ...

  3. python3绘图示例4(基于matplotlib:箱线图、散点图等)

    #!/usr/bin/env python# -*- coding:utf-8 -*- from matplotlib.pyplot import * x=[1,2,3,4]y=[5,4,3,2] # ...

  4. Python基础学习之文件(2)

    文件内建方法 1.输入 read()方法用来直接读取字节到字符串中,最多读取给定数目个字节.如果没有给定size参数(默认值为-1)或size值为负,文件将被读取直至末尾. readline()方法读 ...

  5. Python用户交互与流程控制

    1. 用户交互 python3通过input实现用户交互,与python2的raw_input一样,接收的值都转换成字符串格式.python2中也有一个input,而python2中的input接收的 ...

  6. 搭建TFTP服务器配置

    实验内容: TFTP是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂,开销不大的文件传输服务.TFTP承载在UDP上,提供不可靠的数据传输服务,不提供存取授权与认 ...

  7. MySQL入门很简单: 7 触发器

    触发器是由事件来触发某个操作,这些事件包括INSERT语句,UPDATE语句和DELETE语句 1.创建触发器 1)创建只有一个执行语句的触发器 例子:再向department表中执行INSERT操作 ...

  8. IOS笔记 : 一些小技巧

    计算单元格高度,在自定义cell中 -(void) resizeTheHeight{ CGFloat contentWidth = 280; UIFont *font = [UIFont fontWi ...

  9. POJ-2395 Out of Hay---MST最大边

    题目链接: https://vjudge.net/problem/POJ-2395 题目大意: 求MST中的最大边,和POJ-2495类似 思路: 模板直接过 #include<iostream ...

  10. POJ-2718 Smallest Difference---DFS

    题目链接: https://vjudge.net/problem/POJ-2718 题目大意: 有一列数,对其任意分成两组,每组按一定顺序可以组成一个数.问得到的两个数的差最小是多少. 思路: 直接d ...