`
wx1568037608
  • 浏览: 34764 次
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

对装饰器@wraps的解释(一看就懂)-- 并对装饰器详解

 
阅读更多

1. 先看一段代码

def is_login(func):
    def foo(*args,**kwargs):
        return func(*args,**kwargs)
    return foo

def test():
    print('我是:',test.__name__)

@is_login
def test1():
    print('我是:',test1.__name__)
@is_login
def test2():
    print('我是:',test2.__name__)
    
test()
test1()
test2()

>>>>

我是: test
我是: foo
我是: foo

可以发现函数的函数名即 name已被装饰器改变

2.那我们来增加@wraps

from functools import wraps

def is_login(func):
    @wraps(func)
    def foo(*args,**kwargs):
        return func(*args,**kwargs)
    return foo

def test():
    print('我是:',test.__name__)

@is_login
def test1():
    print('我是:',test1.__name__)
@is_login
def test2():
    print('我是:',test2.__name__)
    
test()
test1()
test2()

>>>>
我是: test
我是: test1
我是: test2

结论:

可以看见@wraps可以保证装饰器修饰的函数的name的值保持不变


补充:装饰的优化

以时间装饰器为例,进行优化

  • 装饰器的统一模板
from functools import wraps
# 对函数的装饰器, 对类func最好为cls
def decorate(func):
    @wraps(func)
    # 增添或修改功能的函数
    def wrapper(*args,**kwargs):
                # 执行被装饰的函数
        result = func(*args,**kwargs) 
        # 返回结果
        return result
    # 返回内层函数
    return wrapper

普通--时间装饰器

from functools import wraps
import time
from random import randint

def use_time(func):
    @wraps(func)
    def wrapper(*args,**kwargs):
        st_time = time.time()
        result = func(*args,**kwargs)
        end_time = time.time()
        print(f'{func.__name__}函数use_time:{end_time-st_time}s')
    return wrapper
 
    
@use_time
def foo():
    time.sleep(randint(1,3))

for _ in range(3):
    foo()

#输出
>>>>
foo函数use_time:1.0007495880126953s
foo函数use_time:3.0018675327301025s
foo函数use_time:3.0030477046966553s

下面对改装饰器进行优化(解耦)

  • 可以发先上面时间装饰器计算的结果,只能在控制台上打印
  • 那我们怎样才能将它输出为日志呢???
  • 我们需要将他的结果进行自定输出
# 在增加一层函数
from functools import wraps
import time
from random import randint

def record(output):
    def use_time(func):
        @wraps(func)
        def wrapper(*args,**kwargs):
            st_time = time.time()
            result = func(*args,**kwargs)
            end_time = time.time()
#             print(f'{func.__name__}函数use_time:{end_time-st_time}s')
            output(func.__name__, end_time-st_time)
        return wrapper
    return use_time

# 改装饰器的结果就可以自定义了,下面以print函数为例
@record(print)
def foo():
    time.sleep(randint(2,5))

for _ in range(3):
    foo()
>>>>
foo 3.000645875930786
foo 4.003818988800049
foo 2.0020666122436523

结果输出日志

  • 只需要自己定义一个函数
def write_log(name,content):
    with open('./time.log','a')as f:
        f.write(f'{name}耗时:{content}\r\n') # \r\n 换行
        
# 只需要将装饰器改为@record(write_log)
@record(write_log)
def foo():
    time.sleep(randint(2,5))

for _ in range(3):
    foo()

效果如下

 
效果如图


作者:憧憬001
链接:https://www.jianshu.com/p/5df1769e562e
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
分享到:
评论

相关推荐

    Python中的各种装饰器详解

    4. **@wraps装饰器**: - 当编写自定义装饰器时,为了保持被装饰函数的元信息(如函数名、文档字符串等),可以使用`functools.wraps`装饰器。例如,`@wraps(func)`可以确保装饰后的函数保持原始函数的名称和文档。...

    python——retry装饰器(csdn)————程序.pdf

    Python retry 装饰器详解 Python 语言中,retry 装饰器是一种非常有用的机制,能够帮助开发者在编写代码时,轻松地实现函数的重试机制。本文将对 Python 中的 retry 装饰器进行详细的讲解,包括其定义、使用方法、...

    Python装饰器使用你可能不知道的几种姿势

    装饰器本质上是一个接受函数作为参数并返回一个新函数的函数,通常用于在函数执行前后添加一些额外的操作。在Python中,装饰器是一个非常灵活且功能强大的工具,可以用来计时、缓存、权限校验、日志记录、异常处理等...

    Python库 | wrapt-1.13.3rc1-cp36-cp36m-manylinux2010_x86_64.whl

    一旦安装完成,你就可以在你的Python项目中导入并使用wrapt库,以实现各种复杂的装饰器逻辑,提高代码的可维护性和可扩展性。 总结来说,wrapt是一个强大的Python库,专注于装饰器的实现,提供了高级特性如元信息...

    Python装饰器实现方法及应用场景详解

    ### Python装饰器实现方法及应用场景详解 #### 一、装饰器概述 装饰器是一种特殊类型的Python函数,它可以修改其他函数的功能或行为。装饰器的基本原理是利用Python的高阶函数特性,即函数可以作为参数传递给其他...

    Python 装饰器原理、定义与用法详解

    装饰器本质上是一个接收函数作为参数并返回新函数的函数,它能够插入额外的行为到其他函数或类中。 1. 装饰器的原理: 装饰器的工作原理在于,它将一个函数包装(即“装饰”)成另一个函数,以添加额外的功能或修改...

    Python 带有参数的装饰器实例代码详解

    这样,装饰器就包裹了目标函数,并在实际调用目标函数时,先执行装饰器内的逻辑。 在`demo.py`中,有两个被装饰的函数`test1`和`test2`: ```python @set_level(1) def test1(): print("-----test1---") return ...

    Python中装饰器兼容加括号和不加括号的写法详解

    ### Python中装饰器兼容加括号和不加括号的写法详解 在Python编程语言中,装饰器是一种强大的工具,用于修改或增强其他函数的行为而无需改变其源代码。装饰器可以接受参数来定制其行为,这为用户提供了一种灵活的...

    Python类中的装饰器在当前类中的声明与调用详解

    ### Python 类中的装饰器在当前类中的声明与调用详解 #### 一、引言 在 Python 中,装饰器是一种非常强大的工具,它允许开发者在不修改原函数的基础上增加额外的功能,例如日志记录、性能测量、事务处理、缓存等。...

    python中的装饰器详解

    在编写装饰器时,通常使用functools模块中的wraps装饰器来增强被包装函数的元数据。它能够将被装饰函数的名称、文档字符串等元数据复制到包装函数中,这样可以确保被装饰函数的文档字符串等信息不会丢失,且在使用...

    详解Python中的装饰器、闭包和functools的教程

    此外,通过使用wraps装饰器,可以保持被装饰函数的元数据信息,如函数名和文档字符串。 对于需要对函数执行时间进行监控的场景,作者还提供了一个更高级的示例,这个示例通过缓存机制实现了一个缓存装饰器。在这个...

    Python装饰器(decorator)定义与用法详解

    装饰器本质上是一个Python函数,它可以接收一个函数作为参数,并返回一个新的函数。这种设计模式在处理如日志记录、性能测试、事务处理等场景时非常有用。 在Python中,装饰器通过`@decorator`的语法糖来使用,使得...

    PyPI 官网下载 | wrapt-1.10.8.tar.gz

    1. **函数和方法的透明包装**:wrapt库中的`@wraps`装饰器可以确保被装饰的函数或方法的元数据(如名称、文档字符串等)得以保留,这样在调试和使用时能保持原有的可读性。 2. **动态拦截和修改行为**:通过wrapt的...

    Python函数装饰器常见使用方法实例详解

    Python函数装饰器是一种高级函数,它能够用于修改或增强其他函数的功能,而无需直接改动被装饰的函数的源代码或调用方式。装饰器在Python中广泛应用,它们遵循开放封闭原则,即允许对软件功能进行扩展,而不改变原有...

    python装饰器原理与用法深入详解

    来看一个简单的装饰器例子,我们使用一个装饰器来计算函数的执行时间: ```python import time def deco(func): def wrapper(): start_time = time.time() func() end_time = time.time() print(f"{func.__...

Global site tag (gtag.js) - Google Analytics