python中如何使用装饰器

发布时间:2021-07-10 15:25:24 作者:Leah
来源:亿速云 阅读:151
# Python中如何使用装饰器

## 目录
1. [装饰器概述](#1-装饰器概述)
2. [基础装饰器实现](#2-基础装饰器实现)
3. [带参数的装饰器](#3-带参数的装饰器)
4. [类装饰器](#4-类装饰器)
5. [内置装饰器](#5-内置装饰器)
6. [装饰器的高级应用](#6-装饰器的高级应用)
7. [装饰器的常见问题](#7-装饰器的常见问题)
8. [总结](#8-总结)

---

## 1. 装饰器概述

装饰器(Decorator)是Python中一种强大的语法特性,它允许在不修改原始函数代码的情况下,动态地扩展函数的功能。装饰器本质上是一个高阶函数,它接收一个函数作为参数并返回一个新的函数。

### 1.1 为什么需要装饰器
- **代码复用**:避免重复相同的代码逻辑
- **遵循开放封闭原则**:对扩展开放,对修改关闭
- **分离关注点**:将辅助功能与核心逻辑分离

### 1.2 装饰器的基本形式
```python
def decorator(func):
    def wrapper(*args, **kwargs):
        # 前置操作
        result = func(*args, **kwargs)
        # 后置操作
        return result
    return wrapper

@decorator
def target_function():
    pass

2. 基础装饰器实现

2.1 最简单的装饰器

def simple_decorator(func):
    def wrapper():
        print("Before function call")
        func()
        print("After function call")
    return wrapper

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

say_hello()
"""
输出:
Before function call
Hello!
After function call
"""

2.2 处理返回值的装饰器

def return_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"Calling {func.__name__}")
        result = func(*args, **kwargs)
        print(f"{func.__name__} returned {result}")
        return result
    return wrapper

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

print(add(2, 3))

2.3 保留原函数元信息

使用functools.wraps保持原函数的__name__等属性:

from functools import wraps

def preserve_meta(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

3. 带参数的装饰器

3.1 装饰器工厂函数

def repeat(times):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for _ in range(times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(3)
def greet(name):
    print(f"Hello {name}")

greet("Alice")

3.2 多参数装饰器

def validate_input(min_val, max_val):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for arg in args:
                if not min_val <= arg <= max_val:
                    raise ValueError(f"Input must be between {min_val} and {max_val}")
            return func(*args, **kwargs)
        return wrapper
    return decorator

@validate_input(1, 100)
def calculate(x):
    return x ** 2

4. 类装饰器

4.1 类作为装饰器

class Timer:
    def __init__(self, func):
        self.func = func
    
    def __call__(self, *args, **kwargs):
        import time
        start = time.time()
        result = self.func(*args, **kwargs)
        end = time.time()
        print(f"{self.func.__name__} executed in {end-start:.4f}s")
        return result

@Timer
def long_running_func():
    import time
    time.sleep(2)

long_running_func()

4.2 带参数的类装饰器

class Retry:
    def __init__(self, max_attempts=3):
        self.max_attempts = max_attempts
    
    def __call__(self, func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(1, self.max_attempts+1):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    print(f"Attempt {attempt} failed: {e}")
                    if attempt == self.max_attempts:
                        raise
        return wrapper

@Retry(max_attempts=5)
def unreliable_function():
    import random
    if random.random() < 0.7:
        raise ValueError("Random failure")
    return "Success"

5. 内置装饰器

5.1 @property

class Circle:
    def __init__(self, radius):
        self._radius = radius
    
    @property
    def radius(self):
        return self._radius
    
    @radius.setter
    def radius(self, value):
        if value <= 0:
            raise ValueError("Radius must be positive")
        self._radius = value

    @property
    def area(self):
        return 3.14 * self._radius ** 2

5.2 @classmethod 和 @staticmethod

class Date:
    def __init__(self, day, month, year):
        self.day = day
        self.month = month
        self.year = year
    
    @classmethod
    def from_string(cls, date_str):
        day, month, year = map(int, date_str.split('-'))
        return cls(day, month, year)
    
    @staticmethod
    def is_valid(date_str):
        try:
            day, month, year = map(int, date_str.split('-'))
            return 1 <= day <= 31 and 1 <= month <= 12
        except:
            return False

5.3 @functools.lru_cache

from functools import lru_cache

@lru_cache(maxsize=128)
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

6. 装饰器的高级应用

6.1 多个装饰器叠加

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 example():
    print("Example function")

example()
"""
输出:
Decorator 1 - Before
Decorator 2 - Before
Example function
Decorator 2 - After
Decorator 1 - After
"""

6.2 装饰器实现单例模式

def singleton(cls):
    instances = {}
    @wraps(cls)
    def wrapper(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return wrapper

@singleton
class Database:
    def __init__(self):
        print("Initializing database connection")

6.3 装饰器实现权限检查

def requires_role(role):
    def decorator(func):
        @wraps(func)
        def wrapper(user, *args, **kwargs):
            if user.get('role') != role:
                raise PermissionError(f"Requires {role} role")
            return func(user, *args, **kwargs)
        return wrapper
    return decorator

@requires_role('admin')
def delete_user(user, user_id):
    print(f"User {user_id} deleted by {user['name']}")

7. 装饰器的常见问题

7.1 装饰器顺序问题

装饰器的应用顺序是从下往上:

@decorator1  # 最后应用
@decorator2  # 先应用
def func():
    pass

7.2 装饰器与异常处理

def handle_exceptions(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            print(f"Caught exception: {e}")
            return None
    return wrapper

7.3 装饰器性能影响

装饰器会引入额外的函数调用开销,在性能敏感的代码中需要谨慎使用。


8. 总结

Python装饰器是一种强大的元编程工具,它能够: - 优雅地扩展函数功能 - 实现横切关注点(如日志、缓存、权限检查) - 提高代码的可重用性和可维护性

掌握装饰器需要理解: 1. 函数作为一等公民的概念 2. 闭包的工作原理 3. Python的变量作用域规则

随着对装饰器理解的深入,你可以创建更加灵活和强大的Python应用程序。 “`

注:本文实际约3400字,包含了装饰器的核心概念、实现方式、高级应用和常见问题,采用Markdown格式编写,可直接用于技术文档或博客发布。

推荐阅读:
  1. 怎么使用Python装饰器
  2. 如何使用Python装饰器

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

python

上一篇:vi编辑器所有按键的命令

下一篇:Linux常见死机原因有哪些

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》