Python装饰器自学全解
2026/9/24 17:57:44 网站建设 项目流程

1. 关于装饰器这一概念的基本知识, 其中的第一小节内容探讨了这样一个问题, 即究竟什么是装饰器?

装饰器属于一种设计模式, 这种设计模式允许在不修改原始函数代码的前提情况下, 往函数内部添加全新的功能内容, 它属于语法糖的一种范畴, 是基于闭包机制以及高阶函数来实现相关效果的。

1.第2点, 装饰器究竟是什么东西。

从本质上来讲, 这个可调用对象就是装饰器。它的主要功能是接收一个函数当作参数。然后它会返回一个新的函数给你。

def decorator(func):

def wrapper(*args, **kwargs):

# 添加新功能

result = func(*args, **kwargs)

# 添加新功能

return result

return wrapper

2. 关于装饰器的基础知识这一部分, 我们来到了第二小节, 也就是编号为2.1的函数基础知识回顾环节。

# 1. 函数是一等公民:可以赋值给变量

def greet(name):

return f"Hello, {name}!"

say_hello = greet # 函数赋值给变量

print(say_hello("Alice")) # Hello, Alice!

# 2. 函数可以作为参数传递

def apply_function(func, value):

return func(value)

def square(x):

return x * x

print(apply_function(square, 5)) # 25

# 3. 函数可以嵌套定义

def outer():

def inner():

return "Inner function"

return inner()

# 4. 闭包:函数可以记住它被创建时的环境

def make_multiplier(n):

def multiplier(x):

return x * n

return multiplier

times_3 = make_multiplier(3)

print(times_3(4)) # 12

3. 针对基础级别的装饰器这一块内容, 我们展开详细讲解。

# 最简单的装饰器

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_decorator

def say_hello():

print("Hello!

")

say_hello()

# 输出:

# Something is happening before the function is called.

# Hello!

# Something is happening after the function is called.

3.这是关于第二个部分的内容, 主要是讲解那些带有参数的函数装饰器。

def timer_decorator(func):

import time

def wrapper(*args, **kwargs):

start_time = time.time()

result = func(*args, **kwargs)

end_time = time.time()

print(f"{func.__name__} executed in {end_time - start_time:.4f} seconds")

return result

return wrapper

@timer_decorator

def slow_function(seconds):

time.sleep(seconds)

return f"Slept for {seconds} seconds"

print(slow_function(2))

# 输出:

# slow_function executed in 2.0023 seconds

# Slept for 2 seconds

3.3 带参数的装饰器

def repeat(num_times):

"""装饰器工厂函数,返回一个装饰器"""

def decorator_repeat(func):

def wrapper(*args, **kwargs):

for _ in range(num_times):

result = func(*args, **kwargs)

return result

return wrapper

return decorator_repeat

@repeat(num_times=3)

def greet(name):

print(f"Hello, {name}!

")

greet("Alice")

# 输出:

# Hello, Alice!

# Hello, Alice!

# Hello, Alice!

3.4 保留函数元信息

from functools import wraps

def preserve_metadata_decorator(func):

@wraps(func) # 使用wraps保留原函数的元信息

def wrapper(*args, **kwargs):

"""包装函数的文档"""

print(f"Calling {func.__name__}")

return func(*args, **kwargs)

return wrapper

@preserve_metadata_decorator

def calculate_sum(a, b):

"""计算两个数的和"""

return a + b

print(calculate_sum.__name__) # calculate_sum(如果不使用wraps会是wrapper)

print(calculate_sum.__doc__) # 计算两个数的和

print(calculate_sum(3, 4)) # 7

4. 所谓类装饰器这一章节的内容, 其主题是讨论4.1部分, 也就是要把一个类当作装饰器来使用的情景。

class TimerDecorator:

def __init__(self, func):

self.func = func

def __call__(self, *args, **kwargs):

import time

start_time = time.time()

result = self.func(*args, **kwargs)

end_time = time.time()

print(f"Execution time: {end_time - start_time:.4f} seconds")

return result

@TimerDecorator

def long_running_operation():

time.sleep(1)

return "Operation completed"

print(long_running_operation())

4.2 带参数的类装饰器

class RetryDecorator:

def __init__(self, max_retries=3):

self.max_retries = max_retries

def __call__(self, func):

def wrapper(*args, **kwargs):

for attempt in range(self.max_retries):

try:

return func(*args, **kwargs)

except Exception as e:

if attempt == self.max_retries - 1:

raise

print(f"Attempt {attempt + 1} failed: {e}. Retrying...")

return None

return wrapper

@RetryDecorator(max_retries=3)

def unstable_function():

import random

if random.random() < 0.7:

raise ValueError("Random failure!

")

return "Success!

"

print(unstable_function())

5. 关于另外的一些装饰器的应用, 在章节的第五点第一个小标题部分, 提到了存在多个装饰器这样的状况。

def decorator1(func):

@wraps(func)

def wrapper(*args, **kwargs):

print("Decorator 1: Before")

result = func(*args, **kwargs)

print("Decorator 1: After")

return result

return wrapper

def decorator2(func):

@wraps(func)

def wrapper(*args, **kwargs):

print("Decorator 2: Before")

result = func(*args, **kwargs)

print("Decorator 2: After")

return result

return wrapper

@decorator1

@decorator2

def say_hello():

print("Hello!

")

say_hello()

# 输出:

# Decorator 1: Before

# Decorator 2: Before

# Hello!

# Decorator 2: After

# Decorator 1: After

# 注意:装饰器从下往上执行

5.第2部分要讲的是装饰器以及与类方法相关的这些内容。

def method_decorator(func):

@wraps(func)

def wrapper(self, *args, **kwargs):

print(f"Calling method {func.__name__} on {self}")

return func(self, *args, **kwargs)

return wrapper

class Calculator:

def __init__(self, value=0):

self.value = value

@method_decorator

def add(self, x):

self.value += x

return self.value

@method_decorator

def multiply(self, x):

self.value *= x

return self.value

calc = Calculator(10)

print(calc.add(5)) # 15

print(calc.multiply(2)) # 30

6. 关于装饰器的应用示例第6点1, 也就是缓存这个装饰器。

from functools import lru_cache

# 使用内置的lru_cache装饰器

@lru_cache(maxsize=128)

def fibonacci(n):

if n < 2:

return n

return fibonacci(n-1) + fibonacci(n-2)

# 自定义缓存装饰器

def memoize(func):

cache = {}

@wraps(func)

def wrapper(*args, **kwargs):

key = str(args) + str(kwargs)

if key not in cache:

cache[key] = func(*args, **kwargs)

return cache[key]

return wrapper

@memoize

def expensive_computation(x):

print(f"Computing for {x}...")

import time

time.sleep(1)

return x * x

print(expensive_computation(5)) # 会打印"Computing for 5..."

print(expensive_computation(5)) # 直接从缓存返回,不会打印

6.这是一个用于权限验证装饰器的条目。

def require_permission(permission):

def decorator(func):

@wraps(func)

def wrapper(user, *args, **kwargs):

if permission not in user.get('permissions', []):

raise PermissionError(f"User lacks {permission} permission")

return func(user, *args, **kwargs)

return wrapper

return decorator

class UserManager:

@require_permission('admin')

def delete_user(self, user, target_user):

return f"User {target_user} deleted by {user['name']}"

@require_permission('editor')

def edit_content(self, user, content):

return f"Content edited by {user['name']}"

admin_user = {'name': 'Alice', 'permissions': ['admin', 'editor']}

editor_user = {'name': 'Bob', 'permissions': ['editor']}

regular_user = {'name': 'Charlie', 'permissions': []}

manager = UserManager()

print(manager.delete_user(admin_user, 'old_user')) # 正常执行

# print(manager.delete_user(editor_user, 'old_user')) # 抛出PermissionError

6.这第3项是关于日志装饰器的一个内容说明。

import logging

from datetime import datetime

logging.basicConfig(level=logging.INFO)

def log_decorator(func):

@wraps(func)

def wrapper(*args, **kwargs):

start_time = datetime.now()

logging.info(f"Starting {func.__name__} at {start_time}")

try:

result = func(*args, **kwargs)

end_time = datetime.now()

duration = (end_time - start_time).total_seconds()

logging.info(f"Finished {func.__name__} in {duration:.2f}s")

return result

except Exception as e:

logging.error(f"Error in {func.__name__}: {e}")

raise

return wrapper

@log_decorator

def process_data(data):

import time

time.sleep(0.5)

return [x * 2 for x in data]

print(process_data([1, 2, 3, 4, 5]))

6.第4部分是关于类型检查装饰器的内容。

def type_check(**types):

def decorator(func):

@wraps(func)

def wrapper(*args, **kwargs):

# 检查位置参数

for i, (arg, (param_name, expected_type)) in enumerate(

zip(args, types.items())

):

if not isinstance(arg, expected_type):

raise TypeError(

f"Argument '{param_name}' must be {expected_type}, "

f"got {type(arg)}"

)

# 检查关键字参数

for param_name, value in kwargs.items():

if param_name in types and not isinstance(value, types[param_name]):

raise TypeError(

f"Argument '{param_name}' must be {types[param_name]}, "

f"got {type(value)}"

)

return func(*args, **kwargs)

return wrapper

return decorator

@type_check(x=int, y=int)

def add_numbers(x, y):

return x + y

print(add_numbers(5, 3)) # 8

# print(add_numbers(5, "3")) # 抛出TypeError

7. 关于装饰器的调试工作以及测试环节, 其中需要着重关注的是第7.1小节所涉及的如何对装饰器进行调试这一具体问题的展开说明。

def debug_decorator(func):

@wraps(func)

def wrapper(*args, **kwargs):

print(f"[DEBUG] Calling {func.__name__}")

print(f"[DEBUG] Args: {args}")

print(f"[DEBUG] Kwargs: {kwargs}")

result = func(*args, **kwargs)

print(f"[DEBUG] {func.__name__} returned: {result}")

return result

return wrapper

@debug_decorator

def divide(a, b):

return a / b

divide(10, 2)

7.2 测试装饰器

import unittest

def validate_input(min_value=0, max_value=100):

def decorator(func):

@wraps(func)

def wrapper(value):

if not (min_value <= value <= max_value):

raise ValueError(

f"Value must be between {min_value} and {max_value}"

)

return func(value)

return wrapper

return decorator

@validate_input(min_value=0, max_value=100)

def process_score(score):

return "Pass" if score >= 60 else "Fail"

class TestDecorator(unittest.TestCase):

def test_valid_score(self):

self.assertEqual(process_score(75), "Pass")

self.assertEqual(process_score(45), "Fail")

def test_invalid_score(self):

with self.assertRaises(ValueError):

process_score(150)

with self.assertRaises(ValueError):

process_score(-10)

if __name__ == "__main__":

unittest.main()

8. 要避免出现, 在循环里面去定义装饰器的这样的操作行为。

# 陷阱:在循环中定义装饰器

def create_decorators():

decorators = []

for i in range(3):

def my_decorator(func):

def wrapper():

print(f"Decorator {i}")

return func()

return wrapper

decorators.append(my_decorator)

return decorators # 所有装饰器都会打印"Decorator 2"

# 正确做法:使用闭包捕获变量

def create_decorator_fixed(n):

def my_decorator(func):

def wrapper():

print(f"Decorator {n}")

return func()

return wrapper

return my_decorator

9. 总结

装饰器是中强大且灵活的特性,它允许我们:

增强函数的功能, 意味着我们可以做到无需修改原始函数代码, 从而实现代码复用将通用功能封装在装饰器里面。这能够保持代码整洁, 把关注点进行分离, 使代码变得更易于维护。它有助于实现面向切面编程, 比如进行日志处理, 或者执行权限验证等等。

掌握装饰器需要理解:

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询