简述python中functools.wrapper()

首先对于最简单的函数:

def a():
pass if __name__ == '__main__':
print(a.__name__)

输出结果:

a

然后稍微复杂点:

def a(func):
def wrapper()
return func @a
def b():
pass if __name__ == '__main__'
print(b.__name__)

输出结果:

a

当加上functools.wrapper时:

def a(func):
@functools.wrapper(func)
def wrapper()
return func @a
def b():
pass if __name__ == '__main__'
print(b.__name__)

输出结果:

b

很明显,通过调用functools.wrapper()使得返回值发生了改变,这其实与它的函数定义有关,代码如下:

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)
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
class partial:
"""New function with partial application of the given arguments
and keywords.
""" __slots__ = "func", "args", "keywords", "__dict__", "__weakref__" def __new__(cls, func, /, *args, **keywords):
if not callable(func):
raise TypeError("the first argument must be callable") if hasattr(func, "func"):
args = func.args + args
keywords = {**func.keywords, **keywords}
func = func.func self = super(partial, cls).__new__(cls) self.func = func
self.args = args
self.keywords = keywords
return self def __call__(self, /, *args, **keywords):
keywords = {**self.keywords, **keywords}
return self.func(*self.args, *args, **keywords) @recursive_repr()
def __repr__(self):
qualname = type(self).__qualname__
args = [repr(self.func)]
args.extend(repr(x) for x in self.args)
args.extend(f"{k}={v!r}" for (k, v) in self.keywords.items())
if type(self).__module__ == "functools":
return f"functools.{qualname}({', '.join(args)})"
return f"{qualname}({', '.join(args)})" def __reduce__(self):
return type(self), (self.func,), (self.func, self.args,
self.keywords or None, self.__dict__ or None) def __setstate__(self, state):
if not isinstance(state, tuple):
raise TypeError("argument to __setstate__ must be a tuple")
if len(state) != 4:
raise TypeError(f"expected 4 items in state, got {len(state)}")
func, args, kwds, namespace = state
if (not callable(func) or not isinstance(args, tuple) or
(kwds is not None and not isinstance(kwds, dict)) or
(namespace is not None and not isinstance(namespace, dict))):
raise TypeError("invalid partial state") args = tuple(args) # just in case it's a subclass
if kwds is None:
kwds = {}
elif type(kwds) is not dict: # XXX does it need to be *exactly* dict?
kwds = dict(kwds)
if namespace is None:
namespace = {} self.__dict__ = namespace
self.func = func
self.args = args
self.keywords = kwds try:
from _functools import partial
except ImportError:
pass

上面大致讲的呢,就是通过调用functools.wrappers()来创建了不一样的函数,但是名字却是一样的,且id不一样,功能也可能会有所改变。代码如下:

import functools

def m(func):
print(func.__name__)
print(id(func))
@functools.wraps(func)
def wrapper():
print(wrapper.__name__)
print(id(wrapper))
return wrapper def method1():
pass @m
def method2():
print(id(method2)) if __name__ == '__main__':
print(method2())

输出:

method2
1868266070224
method2
1868266070368
None

综上:调用该函数创建了另一个名字一样的函数,但是内部构造可能会不相同。

简述python中`functools.wrapper()的更多相关文章

  1. 简述Python中的break和continue的区别

    众所周知在Python中,break是结束整个循环体,而continue则是结束本次循环再继续循环. 但是作为一个新手的你,还是不明白它们的区别,这里用一个生动的例子说明它们的区别,如下: 1.con ...

  2. Python中functools模块函数解析

    Python自带的 functools 模块提供了一些常用的高阶函数,也就是用于处理其它函数的特殊函数.换言之,就是能使用该模块对可调用对象进行处理. functools模块函数概览 functool ...

  3. python中 functools模块 闭包的两个好朋友partial偏函数和wraps包裹

    前一段时间学习了python当中的装饰器,主要利用了闭包的原理.后来呢,又见到了python当中的functools模块,里面有很多实用的功能.今天我想分享一下跟装饰器息息相关的两个函数partial ...

  4. python中functools.wraps装饰器的作用

    functools.wraps装饰器用于显示被包裹的函数的名称 import functools def node(func): #@functools.wraps(func) def wrapped ...

  5. python中functools.singledispatch的使用

    from functools import singledispatch @singledispatch def show(obj): print (obj, type(obj), "obj ...

  6. 简述python中的@staticmethod作用及用法

    关于@staticmethod,这里抛开修饰器的概念不谈,只简单谈它的作用和用法. staticmethod用于修饰类中的方法,使其可以在不创建类实例的情况下调用方法,这样做的好处是执行效率比较高.当 ...

  7. Python中表达式与语句

    简述 Python中我暂时并未发现谁对着两个名词的明确定义:我对这两个名词的理解就是,表达式就是你想要执行的对象,语句就是你的具体执行操作. 这里应用慕课网老师的一段话,摘自网上"表达式(E ...

  8. python中的functools模块

    functools模块可以作用于所有的可以被调用的对象,包括函数 定义了__call__方法的类等 1 functools.cmp_to_key(func) 将比较函数(接受两个参数,通过比较两个参数 ...

  9. Python 中实现装饰器时使用 @functools.wraps 的理由

    Python 中使用装饰器对在运行期对函数进行一些外部功能的扩展.但是在使用过程中,由于装饰器的加入导致解释器认为函数本身发生了改变,在某些情况下——比如测试时——会导致一些问题.Python 通过  ...

随机推荐

  1. springboot手动事务回滚

    亲测在使用@Transactional.@Transactional(rollbackFor = Exception.class)及catch异常之后 throw new RuntimeExcepti ...

  2. Asp.NetCore3.1 WebApi 使用Jwt 授权认证使用

    1:导入NuGet包 Microsoft.AspNetCore.Authentication.JwtBearer 2:配置 jwt相关信息 3:在 startUp中 public void Confi ...

  3. queue stack for STL

    前不久发现自己vector有些不会了,于是想起了queue和stack. 有一个小故事,,,某天我跟自己打赌我queue没有写博园,结果打开一看竟然不知什么时候写过了,而且(QAQ)还有一定的浏览量了 ...

  4. Kubernetes/K8s CKA认证全套实训视频教程下载

    地址: 链接:https://pan.baidu.com/s/1bwEUZTCVzqM3mGjrlISbcg 提取码:r1kx 目录: 目录: │ 1-1.kubernetes理论教程 - 云原生技术 ...

  5. 如何阅读一本书——分析阅读Pre

    如何阅读一本书--分析阅读Pre 前情介绍 作者: 莫提默.艾德勒 查尔斯.范多伦 初版:1940年,一出版就是全美畅销书榜首一年多.钢铁侠Elon.Musk学过. 需要注意的句子: 成功的阅读牵涉到 ...

  6. vue脚手架创建项目名字报错

    vue inti webpack TimeManger 报错 Sorry, name can no longer contain capital letters 原来这个capital是大写的意思,上 ...

  7. 2020牛客暑假多校训练营 第二场 H Happy Triangle set 线段树 分类讨论

    LINK:Happy Triangle 这道题很容易. 容易想到 a+b<x a<x<b x<a<b 其中等于的情况在第一个和第三个之中判一下即可. 前面两个容易想到se ...

  8. Use SQL to Query Data from CDS and Dynamics 365 CE

    from : https://powerobjects.com/2020/05/20/use-sql-to-query-data-from-cds-and-dynamics-365-ce/ Have ...

  9. 《JavaScript语言入门教程》记录整理:运算符、语法和标准库

    目录 运算符 算数运算符 比较运算符 布尔运算符 二进制位运算符 void和逗号运算符 运算顺序 语法 数据类型的转换 错误处理机制 编程风格 console对象和控制台 标准库 Object对象 属 ...

  10. 极简 Node.js 入门 - 1.2 模块系统

    极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...