Python的装饰器介绍

Python装饰器是一个强大的工具,可以增强函数或方法的功能而不改变它们的源代码。装饰器本质上是高阶函数(即接受一个函数作为参数的函数),它允许我们在函数的入口和出口添加逻辑,这使得代码更简洁、更具可维护性。下面是对Python装饰器的详细介绍。

1. 装饰器的基本概念

装饰器是一种函数,用于修改或扩展其他函数或方法的行为。它接受一个函数作为参数,并返回一个新的函数。装饰器通常使用@语法糖来应用到函数上。

基本示例

 

def simple_decorator(f): def wrapper(): print("Something is happening before the function is called.") f() print("Something is happening after the function is called.") return wrapper @simple_decorator def say_hello(): print("Hello!") say_hello()

在上面的示例中,simple_decorator函数是一个装饰器,它接受say_hello函数并返回一个新的wrapper函数。wrapper函数在调用f()(即say_hello)之前和之后打印消息。

2. 装饰器的应用场景

2.1 日志记录

装饰器可以用于添加日志记录功能,以便在调用函数时记录日志信息。

 

def log_decorator(f): def wrapper(*args, **kwargs): print(f"Calling function {f.__name__} with arguments {args} and keyword arguments {kwargs}") result = f(*args, **kwargs) print(f"Function {f.__name__} returned {result}") return result return wrapper @log_decorator def add(a, b): return a + b add(2, 3)

2.2 访问控制

装饰器可以用于检查用户权限或其他访问控制措施。

 

def requires_admin(f): def wrapper(*args, **kwargs): user = kwargs.get('user', None) if user is not None and user.get('is_admin', False): return f(*args, **kwargs) else: raise PermissionError("User does not have the required permissions.") return wrapper @requires_admin def delete_user(user_id, user): print(f"User {user_id} has been deleted.") # 示例用法 admin_user = {'username': 'admin', 'is_admin': True} regular_user = {'username': 'guest', 'is_admin': False} delete_user(123, user=admin_user) # 正常执行 delete_user(123, user=regular_user) # 引发PermissionError

2.3 缓存

装饰器可以用于实现函数的缓存,以提高性能。

 

from functools import lru_cache @lru_cache(maxsize=None) def fibonacci(n): if n < 2: return n return fibonacci(n-1) + fibonacci(n-2) print(fibonacci(30))

3. 函数装饰器和类装饰器

除了装饰函数,装饰器还可以用于类。这使得装饰器在面向对象编程中同样强大。

3.1 类装饰器

类装饰器是用于修改类行为的装饰器。它们接收一个类,并返回一个新的类或修改后的类。

 

def add_str_repr(cls): def __str__(self): return f"{self.__class__.__name__} with attributes {self.__dict__}" cls.__str__ = __str__ return cls @add_str_repr class Person: def __init__(self, name, age): self.name = name self.age = age p = Person("Alice", 30) print(p)

3.2 方法装饰器

方法装饰器与函数装饰器类似,但它们用于类的方法。

 

def log_method_call(method): def wrapper(self, *args, **kwargs): print(f"Calling method {method.__name__} with arguments {args} and keyword arguments {kwargs}") return method(self, *args, **kwargs) return wrapper class Person: def __init__(self, name, age): self.name = name self.age = age @log_method_call def greet(self): print(f"Hello, my name is {self.name}") p = Person("Alice", 30) p.greet()

4. 参数化装饰器

参数化装饰器允许我们传递参数给装饰器。为了实现这一点,我们需要创建一个返回装饰器的函数。

 

def repeat(n): def decorator(f): def wrapper(*args, **kwargs): for _ in range(n): f(*args, **kwargs) return wrapper return decorator @repeat(3) def say_hello(): print("Hello!") say_hello()

在上面的示例中,repeat函数是一个参数化装饰器工厂,它返回一个装饰器,该装饰器会将目标函数执行指定的次数。

5. 内置装饰器

Python 提供了一些内置的装饰器,如@staticmethod@classmethod@property,它们用于不同的用途。

5.1 @staticmethod

@staticmethod装饰器用于定义静态方法,即不需要访问实例或类的属性和方法。

 

class Math: @staticmethod def add(a, b): return a + b print(Math.add(3, 5))

5.2 @classmethod

@classmethod装饰器用于定义类方法,即可以访问类本身的属性和方法。

 

class Math: _pi = 3.14 @classmethod def get_pi(cls): return cls._pi print(Math.get_pi())

5.3 @property

@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 c = Circle(5) print(c.radius) c.radius = 10 print(c.radius)

6. 多重装饰器

一个函数可以同时应用多个装饰器,这些装饰器将从内到外依次应用。

 

def bold(f): def wrapper(): return f"<b>{f()}</b>" return wrapper def italic(f): def wrapper(): return f"<i>{f()}</i>" return wrapper @bold @italic def greet(): return "Hello" print(greet())

在上面的示例中,greet函数首先应用@italic装饰器,然后应用@bold装饰器,最终结果是Hello被加粗和斜体显示。

7. 装饰器的实现细节

为了更好地理解装饰器的工作原理,让我们深入探讨一下装饰器的实现细节。

7.1 保持函数元数据

使用functools.wraps装饰器可以确保装饰器不会丢失原始函数的元数据,如名称和文档字符串。

from fuctools import wraps def simple_decorator(f): @wraps(f) def wrapper(*args, **kwargs): print("Something is happening before the function is called.") result = f(*args, **kwargs) print("Something is happening after the function is called.") return result return wrapper @simple_decorator def say_hello(): """This function says hello""" print("Hello!") print(say_hello.__name__) print(say_hello.__doc__)

7.2 处理带参数的装饰器

带参数的装饰器需要多一层包装,以便接收参数。

def decorator_with_args(arg1, arg2): def decorator(f): @wraps(f) def wrapper(*args, **kwargs): print(f"Decorator arguments: {arg1}, {arg2}") return f(*args, **kwargs) return wrapper return decorator @decorator_with_args("hello", "world") def greet(name): print(f"Hello, {name}") greet("Alice")

总结

Python装饰器是一个强大的工具,可以在不修改原始函数或方法的情况下扩展其功能。通过装饰器,我们可以实现日志记录、访问控制、缓存、性能优化等多种功能。此外,装饰器可以应用于函数、方法和类,使得它们在函数式编程和面向对象编程中都能发挥重要作用。理解和熟练应用装饰器将极大地提高代码的可维护性和可重用性。

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值