简述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. Android Studio常见问题集锦

    Android studio无法在可视化页面预览XML布局文件 修改res/values/styles.xml文件中name=“AppTheme”的style,在Theme.AppCompat.Lig ...

  2. 放弃dagger?Anrdoi依赖注入框架koin

    Koin 是什么 Koin 是为 Kotlin 开发者提供的一个实用型轻量级依赖注入框架,采用纯 Kotlin 语言编写而成,仅使用功能解析,无代理.无代码生成.无反射. 官网地址 优势 依赖注入好处 ...

  3. .Net Core AES加解密

    项目中token在传输过程中采用了AES加密,  网上找到的两篇博文都有写问题,在这里记录一下.Net Core 2.2代码中AES加解密的使用: //AES加密 传入,要加密的串和, 解密key p ...

  4. Spring Date JPA实现增删改查

    1.新建一个Cart类 package com.entity; public class Cart { private int id; private int userId; private int ...

  5. 800页的《数据随想录》PDF版电子书|百度网盘免费下载|数据科学领域必读

    百度网盘免费下载|<数据随想录> 提取码:51y7 本电子书内容包含从数据埋点到数据可视化整个链条的内容,同时,也整理了很多小伙伴们在交流社区中常问到的问题<数据百问>系列 数 ...

  6. 社交网站的数据挖掘与分析pdf版本|网盘下载地址附提取码|

    点击此处进入网盘下载地址 提取码:btqx 作者介绍: 马修·罗塞尔(MatthewA.Russell),DigitalReasoningSystems公司的技术副总裁和Zaffra公司的负责人,是热 ...

  7. Python os.open() 方法

    概述 os.open() 方法用于打开一个文件,并且设置需要的打开选项,模式参数mode参数是可选的,默认为 0777.高佣联盟 www.cgewang.com 语法 open()方法语法格式如下: ...

  8. PHP substr_replace() 函数

    实例 把 "Hello" 替换成 "world": <?php高佣联盟 www.cgewang.comecho substr_replace(" ...

  9. PHP print() 函数

    实例 输出一些文本: <?php print "Hello world!"; ?>高佣联盟 www.cgewang.com 定义和用法 print() 函数输出一个或多 ...

  10. PDOStatement::fetchAll

    PDOStatement::fetchAll — 返回一个包含结果集中所有行的数组(PHP 5 >= 5.1.0, PECL pdo >= 0.1.0)高佣联盟 www.cgewang.c ...