笔记-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)
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
随机推荐
- SQL Union和Union All使用方法
格式: [SQL 语句 1]UNION [SQL 语句 2] 对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序: select ID,NAME from A UNION select I ...
- 开源时序服务器influxdb使用
文档 https://influxdb.com/docs/v0.9/introduction/overview.html 配置文件 /etc/opt/influxdb/influxdb.conf re ...
- Python模块与函数
python的程序由包(package).模块(module)和函数组成.模块是处理某一类问题的集合,模块由函数和类组成,包是由一系列模块组成的集合.包必须至少包含一个__init__.py文件,该文 ...
- python 爬糗事百科
糗事百科网站段子爬取,糗事百科是我见过的最简单的网站了!!! #-*-coding:utf8-*- import requests import re import sys reload(sys) s ...
- UIView的层次调整,及子view布局模式自动布局模式(停靠模式)
UIView*view1=[[UIView alloc]initWithFrame:CGRectMake(10,30,300,30)]; view1.backgroundColor=[UIColor ...
- 问题 A: xiaoping学构造函数
题目描述 xiaoping刚接触类的构造和析构函数,对于构造函数的编写比较困惑.zhuangzhuang给小平布置了一道题目,xiaoping苦思两天也无法解答,请你帮帮xiaoping吧. #inc ...
- Java-笔记1
/* 对第一个java程序进行总结 1. java程序编写-编译-运行的过程 编写:我们将编写的java代码保存在以".java"结尾的源文件中 编译:使用javac.exe命令编 ...
- B3942 Censoring
爆炸入口 有一个S串和一个T串,长度均小于1,000,000,设当前串为U串,然后从前往后枚举S串一个字符一个字符往U串里添加,若U串后缀为T,则去掉这个后缀继续流程. 这道题确乎是个很好的联系kmp ...
- tarjan+topsort
题目 缩完点后统计入读为零的点就可以来. 因为缩完点后肯定是DAG #include<iostream> #include<cstdio> #include<algori ...
- 旧文备份:安装cygwin及在console下输入和显示中文
1.下载Cygwin.exe文件,双击安装,首先在"Choose A Download Source"的时候选择"Download Without Installing& ...