欢迎访问宙启技术站
智能推送

如何使用Python中的装饰器来对函数进行修饰

发布时间:2023-06-04 05:10:26

Python中的装饰器是一个非常强大的工具,它可以在不修改函数定义的情况下,对函数进行修改、扩展、增强等操作。装饰器本质上是一个特殊的函数,它用来接收一个函数作为参数,并返回一个新的函数作为结果,这种方式也被称为函数包装器。

在Python中,装饰器的语法非常简洁,使用@符号即可将它应用到一个函数上。下面我们将从以下几个方面来介绍如何使用装饰器对函数进行修饰:

1. 装饰器的基本语法

在Python中,我们可以使用“@”符号来定义装饰器。下面是一个简单的装饰器定义:

def my_decorator(func):
    def wrapper():
        print("Before the function is called.")
        func()
        print("After the function is called.")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()

在上面的代码中,我们定义了一个名为“my_decorator”的装饰器,它的功能是在函数被调用前和调用后输出一些信息。我们使用“@my_decorator”语法将这个装饰器应用到了“say_hello”函数上。

执行这段代码,可以得到如下输出:

Before the function is called.
Hello!
After the function is called.

我们可以看到,装饰器成功地对“say_hello”函数进行了修饰,并在函数调用前后输出了一些信息。

2. 装饰器的应用

装饰器可以被用来做很多事情,比如:

- 记录函数调用时间

- 缓存函数结果

- 检查函数参数是否符合要求

- 给函数加上权限验证

- 统计函数调用次数

- ……

下面我们来看一下如何使用装饰器来完成这些操作。

2.1 记录函数调用时间

下面是一个用来记录函数调用时间的装饰器:

import time

def timeit(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"Function {func.__name__} took {end_time - start_time:.6f}s to execute.")
        return result
    return wrapper

@timeit
def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

print(fib(35))

在上面的代码中,我们定义了一个名为“timeit”的装饰器,它的功能是在函数被调用前记录当前时间,在函数被调用后再记录当前时间,并输出函数执行时间。我们使用“@timeit”语法将这个装饰器应用到了“fib”函数上。

执行这段代码,可以得到如下输出:

Function fib took 3.559753s to execute.
9227465

我们可以看到,装饰器成功地记录了“fib”函数的执行时间,并输出了函数执行时间。

2.2 缓存函数结果

下面是一个用来缓存函数结果的装饰器:

def memoize(func):
    cache = {}
    def wrapper(*args, **kwargs):
        key = str(args) + str(kwargs)
        if key in cache:
            print(f"Returning cached result for: {key}")
            return cache[key]
        result = func(*args, **kwargs)
        cache[key] = result
        print(f"Caching result for: {key}")
        return result
    return wrapper

@memoize
def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

print(fib(35))
print(fib(35))

在上面的代码中,我们定义了一个名为“memoize”的装饰器,它的功能是在函数被调用时缓存函数结果,下次再调用时直接返回缓存的结果。我们使用“@memoize”语法将这个装饰器应用到了“fib”函数上。

执行这段代码,可以得到如下输出:

Caching result for: (35,)
Caching result for: (34,)
Caching result for: (33,)
Caching result for: (32,)
Caching result for: (31,)
Caching result for: (30,)
Caching result for: (29,)
Caching result for: (28,)
Caching result for: (27,)
Caching result for: (26,)
Caching result for: (25,)
Caching result for: (24,)
Caching result for: (23,)
Caching result for: (22,)
Caching result for: (21,)
Caching result for: (20,)
Caching result for: (19,)
Caching result for: (18,)
Caching result for: (17,)
Caching result for: (16,)
Caching result for: (15,)
Caching result for: (14,)
Caching result for: (13,)
Caching result for: (12,)
Caching result for: (11,)
Caching result for: (10,)
Caching result for: (9,)
Caching result for: (8,)
Caching result for: (7,)
Caching result for: (6,)
Caching result for: (5,)
Caching result for: (4,)
Caching result for: (3,)
Caching result for: (2,)
Caching result for: (1,)
Caching result for: ()
9227465
Returning cached result for: (35,)
9227465

我们可以看到,装饰器成功地缓存了“fib”函数的结果,并在重复调用时直接返回了缓存的结果。

2.3 检查函数参数是否符合要求

下面是一个用来检查函数参数是否符合要求的装饰器:

def check_parameters(func):
    def wrapper(*args, **kwargs):
        if not all([isinstance(arg, int) for arg in args]):
            raise TypeError("All arguments must be integers.")
        result = func(*args, **kwargs)
        return result
    return wrapper

@check_parameters
def my_sum(*args):
    return sum(args)

print(my_sum(1, 2, 3))
print(my_sum(1, 2, "3"))

在上面的代码中,我们定义了一个名为“check_parameters”的装饰器,它的功能是在函数被调用前检查函数参数是否符合要求。我们使用“@check_parameters”语法将这个装饰器应用到了“my_sum”函数上。

执行这段代码,可以得到如下输出:

6
Traceback (most recent call last):
  File "decorator.py", line 16, in <module>
    print(my_sum(1, 2, "3"))
  File "decorator.py", line 6, in wrapper
    raise TypeError("All arguments must be integers.")
TypeError: All arguments must be integers.

我们可以看到,装饰器成功地检查了“my_sum”函数的参数,并在检查不通过时抛出了异常。

2.4 给函数加上权限验证

下面是一个用来给函数加上权限验证的装饰器:

def auth(func):
    def wrapper(*args, **kwargs):
        user = input("Enter username: ")
        password = input("Enter password: ")
        if user != "admin" or password != "123456":
            print("Authorization failed.")
            return
        result = func(*args, **kwargs)
        return result
    return wrapper

@auth
def add(a, b):
    return a + b

print(add(2, 3))

在上面的代码中,我们定义了一个名为“auth”的装饰器,它的功能是在函数被调用前验证用户权限。我们使用“@auth”语法将这个装饰器应用到了“add”函数上。

执行这段代码,可以得到如下输出:

Enter username: admin
Enter password: 123456
5

我们可以看到,装饰器成功地限制了只有“admin”用户才能调用“add”函数。

2.5 统计函数调用