笔记-python-functool-@wraps
笔记-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的更多相关文章
- python functools.wraps functools.partial实例解析
一:python functools.wraps 实例 1. 未使用wraps的实例 #!/usr/bin/env python # coding:utf-8 def logged(func): de ...
- functool.wraps and functools.partial
functools.partial 通过包装手法,允许我们 "重新定义" 函数签名. 通常是将函数的部分参数给固定下来, 从而形成一个输入参数更少的新函数. functool.w ...
- 笔记-python操作mysql
笔记-python操作mysql 1. 开始 1.1. 环境准备-mysql create database db_python; use db_python; create tabl ...
- 笔记-python异常信息输出
笔记-python异常信息输出 1. 异常信息输出 python异常捕获使用try-except-else-finally语句: 在except 语句中可以使用except as e,然后通 ...
- 笔记-python -asynio
笔记-python -asynio 1. 简介 asyncio是做什么的? asyncio is a library to write concurrent code using the a ...
- 笔记-python lib-pymongo
笔记-python lib-pymongo 1. 开始 pymongo是python版的连接库,最新版为3.7.2. 文档地址:https://pypi.org/project/pymong ...
- 笔记-python tutorial-9.classes
笔记-python tutorial-9.classes 1. Classes 1.1. scopes and namespaces namespace: A namespace is ...
- MongoDB学习笔记:Python 操作MongoDB
MongoDB学习笔记:Python 操作MongoDB Pymongo 安装 安装pymongopip install pymongoPyMongo是驱动程序,使python程序能够使用Mong ...
- 机器学习实战笔记(Python实现)-08-线性回归
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
- 机器学习实战笔记(Python实现)-05-支持向量机(SVM)
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
随机推荐
- ASP.NET MVC 音乐商店 - 2.控制器
在典型的 Web 应用中,用户请求的 URL 地址通常映射到保存在网站中的文件上,例如,当用户请求 /Products.aspx 的时候,或者 /Products.php 的时候,很可能是在通过处理 ...
- ComponentOne、Spread、ActiveReports 5折起 加入惊喜惠
慧都十周年,GrapeCity也来共襄盛举,旗下三大产品产品线齐齐参与.界面控件套包ComponentOne.Excel表格控件Spread与报表开发工具ActiveReports,指定授权5折起加入 ...
- EditText中光标的位置设置
CharSequence text = userName.getText(); if (text instanceof Spannable) { ...
- 我的ORM框架
任何系统的基础,都可以算是各种数据的增删改查(CRUD).最早操作数据是直接在代码里写SQL语句,后来出现了各种ORM框架.C#下的ORM框架有很多,如微软自己的Entity Framework.第三 ...
- Linux系统错误码对照表
C Name Value Description EPERM 1 Operation not permitted ENOENT 2 No such file or directory ESRCH 3 ...
- 【转载】#324 - A Generic Class Can Have More than One Type Parameter
A generic class includes one or more type parameters that will be substituted with actual types when ...
- QT OpenGL中文教程在QT4版本后的错误代码更改(一)
由于教程中说的已经够可以了,这里就不对代码进行分析了,有兴趣可以自己去看看.这个教程来源于原来的NeHeOpenGL中文教程 (http://www.yakergong.net/nehe/) ,但其有 ...
- 修改Windows下的Memcached下的服务端口
在命令模式下,可以使用 memcached -p 12000 去指定端口,可服务安装后,却总是只有 -d runservice 的参数. 通过修改注册表来达到这个修改端口的目的. 在 HKEY_LOC ...
- 对类参数的序列化和反序列化XML
/// <summary> /// Xml序列化与反序列化 /// </summary> public class XmlUtil { #region 反序列化 /// < ...
- 【BZOJ3622】已经没有什么好害怕的了(动态规划+广义容斥)
点此看题面 大致题意: 有\(n\)个糖果和\(n\)个药片,各有自己的能量.将其两两配对,求糖果比药片能量大的组数恰好比药片比糖果能量大的组数多\(k\)组的方案数. 什么是广义容斥(二项式反演) ...