笔记-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)
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
随机推荐
- PagerAdapter相关
FragmentPagerAdapter 特点: 应用于少数的(10个以下)fragment:保存在内存中: 只需实现 getItemgetCount()两个方法 FragmentStatePager ...
- Android studio 安装与配置【Android学习入门】
终于下定决心认真学习Android开发了. 之前在很多平台看到很多大牛们学习Android的经验和心得,纸上得来终觉浅. 这里推荐stormzhang老师总结的Android学习之路. 为了防止电脑卡 ...
- zabbix 编译安装指导
zabbix 编译安装 下载 安装 安装后的配置 下载源码包 zabbix官网:https://www.zabbix.com/ zabbix下载:https://www.zabbix.com/down ...
- [QualityCenter]QC是什么?发展历程是怎样?
QC,即Quality Center,是一个基于Web的测试管理工具.它可以组织和管理应用程序测试流程的所有阶段,包括制定测试需求.计划测试.执行测试和跟踪缺陷.此外,通过Quality Center ...
- 如何提升SharePoint 2010的性能
文章来自: http://www.chinaemail.com.cn/server/xtfl/Exchange/201109/66466.html SharePoint是微软历史上销售量增长最快的产品 ...
- char 与 signed char 和 unsigned char三者之间的关系
# char 与 signed char 和 unsigned char三者之间的关系 三者都占用 1个字节,即 8 bit signed char取值范围(-128, 127) unsigned c ...
- 【转】Android xml资源文件中@、@android:type、@*、?、@+含义和区别
一.@代表引用资源 1.引用自定义资源.格式:@[package:]type/name android:text="@string/hello" 2.引用系统资源.格式:@andr ...
- python 爬取猫眼榜单100(二)--多个页面以及多进程
#!/usr/bin/env python # -*- coding: utf- -*- # @Author: Dang Kai # @Date: -- :: # @Last Modified tim ...
- 2017.10.29 C/C++/C#程序如何打成DLL动态库
C/C++程序如何打成DLL动态库: **1.在VS中新建main.h,添加如下内容:** extern "C" _declspec(dllexport) int onLoad() ...
- 用dynamic的方式来转换Json对象
来自这里:http://stackoverflow.com/questions/3142495/deserialize-json-into-c-sharp-dynamic-object If you ...