python函数工具——“三大器”

今天学习装饰器。
装饰器是一个高阶函数,它接受一个函数作为输入并返回一个新的函数,通常用于在不改变原函数代码情况下,增强或修改函数行为。装饰器提供了一种优雅的方法来添加功能或进行函数包装,是python中常用的设计模式。
下面看一个实例便于理解。
def my_decorator(func):def wrapper():        print("Something is happening before the function is called")        func()        print("Something is happening after the function is called")return wrapper@my_decoratordef say_hello():    print("Hello!")say_hello()

outSomething is happening before the function is calledHello!Something is happening after the function is called

多看几遍以上的代码,还有下面的输出结果。假如没有@my_decorator语法糖(syntactic sugar,是指一些简洁和方便的语法结构,它们使代码更易读和编写,但并不会添加新的功能或改变语言的基本行为。),结果是这样:

Hello!
所以我们可以这样理解,有装饰器的存在,改变了say_hello()函数的行为:
@my_decoratordef say_hello():    ...
等价于
def say_hello():...say_hello = my_decorator(say_hello)
使用带参数的装饰器
装饰器不仅可以装饰无参数的函数,也可以装饰有参数的函数。为了实现这一点,需要确保包装函数‘wrapper’能接受任意数量的位置参数和关键词参数。

上面划线部分需要复习之前函数部分,*args是代表可变的位置参数,**kwargs是带边可变的关键词参数

def my_decorator(func):    def wrapper(*args, **kwargs):        print("Before function call")        result = func(*args, **kwargs)        print("After function call")        return result    return wrapper

@my_decoratordef greet(name):    print(f"Hello,{name}!")

greet("Alice")

outBefore function callHello,Alice!After function call

 

装饰器与返回值
装饰器函数可以返回原始函数的返回值,这样包装函数的行为与原始函数一致。
def my_decorator(func):    def wrapper(*args, **kwargs):        print("Before function call")        result = func(*args, **kwargs)        print("After function call")        return result    return wrapper
@my_decoratordef add(a, b):    return a + b
result = add(3, 4)print(f"Result: {result}")
outBefore function callAfter function callResult:11
应用多个装饰器
可以将多个装饰器应用到一个函数,装饰器由内向外依次应用。
def decorator1(func):    def wrapper(*args, **kwargs):        print("Decorator 1 before")        result = func(*args, **kwargs)        print("Decorator 1 after")        return result    return wrapper
def decorator2(func):    def wrapper(*args, **kwargs):        print("Decorator 2 before")        result = func(*args, **kwargs)        print("Decorator 2 after")        return result    return wrapper
@decorator1@decorator2def say_hello():    print("Hello!")
say_hello()

outDecorator 1 beforeDecorator 2 beforeHello!Decorator 2 afterDecorator 1 after
 带参数的装饰器
装饰器本身也可以接受参数。这需要在嵌套一层函数,用于传递参数。
def repeat(num_times):    def decorator(func):        def wrapper(*args, **kwargs):            for _ in range(num_times):                result = func(*args, **kwargs)            return result        return wrapper    return decorator
@repeat(num_times=3)def say_hello():    print("Hello!")
say_hello()
out
Hello!Hello!Hello!
使用‘functools.wraps’保留原函数信息
使用装饰器时,原函数的元数据(如函数名、文档字符串等)可能会丢失。可以使用 functools.wraps 装饰包装函数,保留原函数的元数据。
import functools
def my_decorator(func):    @functools.wraps(func)    def wrapper(*args, **kwargs):        print("Before function call")        result = func(*args, **kwargs)        print("After function call")        return result    return wrapper
@my_decoratordef say_hello():    """This is a docstring for say_hello function."""    print("Hello!")
print(say_hello.__name__)  # 输出:say_helloprint(say_hello.__doc__)   # 输出:This is a docstring for say_hello function.

代码地带

一个简单的缓存装饰器,用于缓存函数的计算结果,避免重复计算。

import functools
def cache(func):    cached_results = {}    @functools.wraps(func)    def wrapper(*args):        if args in cached_results:            return cached_results[args]        result = func(*args)        cached_results[args] = result        return result    return wrapper
@cachedef compute_square(n):    return n * n
print(compute_square(4))  # 输出:16print(compute_square(4))  # 输出:16(使用缓存结果)

原创文章,作者:guozi,如若转载,请注明出处:https://www.sudun.com/ask/89543.html

(0)
guozi的头像guozi
上一篇 2024年6月4日 下午5:02
下一篇 2024年6月4日

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注