Python编写有参数的decorator

开发 前端
在 Python 中,编写有参数的装饰器是一种更高级的技术,它允许我们在装饰器中传递额外的参数,从而实现更灵活的功能。有参数的装饰器可以用于配置装饰器的行为,例如设置日志级别、指定缓存策略等。

前言

在 Python 中,编写有参数的装饰器是一种更高级的技术,它允许我们在装饰器中传递额外的参数,从而实现更灵活的功能。有参数的装饰器可以用于配置装饰器的行为,例如设置日志级别、指定缓存策略等。

1. 带参数的日志记录装饰器

假设我们需要编写一个带参数的日志记录装饰器,用于记录函数的调用和返回值,并指定日志级别。

1.1 示例代码

import logging
def log(level):
    def decorator(func):
        def wrapper(*args, **kwargs):
            logging.log(level, f"Calling function '{func.__name__}'")
            result = func(*args, **kwargs)
            logging.log(level, f"Function '{func.__name__}' returned {result}")
            return result
        return wrapper
    return decorator
@log(logging.DEBUG)
def debug_function():
    return "Debug message"
@log(logging.INFO)
def info_function():
    return "Info message"
logging.basicConfig(level=logging.DEBUG)
debug_result = debug_function()
info_result = info_function()
print(debug_result)  # 输出:Debug message
print(info_result)  # 输出:Info message

在这个例子中,log 装饰器接受一个日志级别作为参数,并返回一个真正的装饰器函数。

2. 带参数的性能统计装饰器

假设我们需要编写一个带参数的性能统计装饰器,用于记录函数的执行时间和次数,并指定统计的精度。

2.1 示例代码

import time
def performance_stats(precisinotallow=4):
    def decorator(func):
        call_count = 0
        total_time = 0.0
        def wrapper(*args, **kwargs):
            nonlocal call_count, total_time
            start_time = time.time()
            print(f"Calling function '{func.__name__}'")
            result = func(*args, **kwargs)
            end_time = time.time()
            elapsed_time = round(end_time - start_time, precision)
            total_time += elapsed_time
            call_count += 1
            print(f"Function '{func.__name__}' returned {result} in {elapsed_time:.{precision}f} seconds")
            print(f"Total calls: {call_count}, Total time: {total_time:.{precision}f} seconds")
            return result
        return wrapper
    return decorator
@performance_stats(precisinotallow=2)
def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n - 1)
result = factorial(5)
print(result)  # 输出:120

在这个例子中,performance_stats 装饰器接受一个精度参数,并返回一个真正的装饰器函数。

3. 带参数的身份验证装饰器

假设我们需要编写一个带参数的身份验证装饰器,用于检查用户是否已登录,并指定允许的用户名。

3.1 示例代码

users = {
    "alice": "password123",
    "bob": "secret456"
}
def login_required(allowed_users):
    def decorator(func):
        def wrapper(username, password, *args, **kwargs):
            if username in allowed_users and allowed_users[username] == password:
                print(f"User '{username}' authenticated")
                return func(username, *args, **kwargs)
            else:
                print("Authentication failed")
                return None
        return wrapper
    return decorator
@login_required(users)
def view_profile(username):
    return f"Profile of user '{username}'"
result = view_profile("alice", "password123")
print(result)  # 输出:Profile of user 'alice'
result = view_profile("bob", "wrongpass")
print(result)  # 输出:None

在这个例子中,login_required 装饰器接受一个允许的用户名字典,并返回一个真正的装饰器函数。

4. 带参数的缓存装饰器

假设我们需要编写一个带参数的缓存装饰器,用于缓存函数的结果,并指定缓存的大小。

4.1 示例代码

from collections import OrderedDict
def memoize(cache_size=100):
    cache = OrderedDict()
    def decorator(func):
        def wrapper(*args, **kwargs):
            key = str(args) + str(kwargs)
            if key not in cache:
                print(f"Computing {func.__name__}({args}, {kwargs})")
                result = func(*args, **kwargs)
                cache[key] = result
                if len(cache) > cache_size:
                    cache.popitem(last=False)
            else:
                print(f"Retrieving {func.__name__}({args}, {kwargs}) from cache")
            return cache[key]
        return wrapper
    return decorator
@memoize(cache_size=10)
def fibonacci(n):
    if n <= 1:
        return n
    else:
        return fibonacci(n - 1) + fibonacci(n - 2)
result = fibonacci(10)
print(result)  # 输出:55

在这个例子中,memoize 装饰器接受一个缓存大小参数,并返回一个真正的装饰器函数。

5. 带参数的日志记录装饰器

假设我们需要编写一个带参数的日志记录装饰器,用于记录函数的调用和返回值,并指定日志文件。

5.1 示例代码

import logging
def log_to_file(log_file):
    logging.basicConfig(filename=log_file, level=logging.DEBUG, format='%(asctime)s %(message)s')
    def decorator(func):
        def wrapper(*args, **kwargs):
            logging.info(f"Calling function '{func.__name__}'")
            result = func(*args, **kwargs)
            logging.info(f"Function '{func.__name__}' returned {result}")
            return result
        return wrapper
    return decorator
@log_to_file("example.log")
def debug_function():
    return "Debug message"
debug_result = debug_function()
with open("example.log", "r") as file:
    log_content = file.read()
    print(log_content)

在这个例子中,log_to_file 装饰器接受一个日志文件名参数,并返回一个真正的装饰器函数。

6. 总结

通过以上示例,我们详细介绍了如何编写有参数的装饰器,并给出了具体的示例代码:

  • 带参数的日志记录装饰器:记录函数的调用和返回值,并指定日志级别。
  • 带参数的性能统计装饰器:记录函数的执行时间和次数,并指定统计的精度。
  • 带参数的身份验证装饰器:检查用户是否已登录,并指定允许的用户名。
  • 带参数的缓存装饰器:缓存函数的结果,并指定缓存的大小。
  • 带参数的日志记录装饰器:记录函数的调用和返回值,并指定日志文件。


责任编辑:华轩 来源: 测试开发学习交流
相关推荐

2021-01-27 11:32:12

接口测试代码

2023-02-01 08:17:48

GitHub提交信息

2009-06-10 11:36:45

有状态的SessionEclipse+JBo

2017-07-27 20:50:55

PythonDecorator装饰器

2009-01-14 10:12:04

Oracle编写事务Oracle控制机制Oracle数据库

2024-03-15 12:48:50

携程AI

2023-11-01 07:41:39

六边形架构适配器架构

2021-02-18 15:43:37

Python装饰器Decorator

2015-06-11 11:10:02

Object-C省略参数

2023-03-27 15:05:10

Python技巧

2016-03-30 11:20:10

2010-02-02 13:59:11

Python编写

2021-03-29 15:32:31

Python函数参数

2023-11-08 14:41:12

Python函数

2021-03-03 10:00:52

Python函数Python基础

2023-09-22 22:49:15

C++重载重写

2010-02-03 09:27:21

编写Python程序

2009-02-01 14:34:26

PythonUnix管道风格

2012-09-13 10:44:18

Python代码

2020-09-30 08:32:40

Python
点赞
收藏

51CTO技术栈公众号