Python装饰器是Python语言中比较重要的一个特性,也是Python编程中的一种高级技巧。Python装饰器允许程序员向一个现有的函数或类添加某些额外的功能,而不用对现有的代码进行修改。在Python开发中,装饰器被广泛应用于Web框架、日志记录、异常处理等方面。
一、Python装饰器的定义
Python装饰器是一种特殊类型的函数,它可以作为其他函数的参数或返回值,实现对其他函数的扩展功能。Python装饰器本质上是一个闭包函数,它将被修饰的函数作为参数传递,并返回一个新的函数,新函数可能会调用原函数,或在原函数前后添加某些操作。Python装饰器的通用写法如下:
```
def decorator(func):
def wrapper(*args, **kwargs):
# do something before the function is called
value = func(*args, **kwargs)
# do something after the function is called
return value
return wrapper
```
其中,decorator就是装饰器,func就是被装饰的函数。
二、Python装饰器的作用
Python装饰器的作用是实现代码的可复用性和可扩展性。通过使用装饰器,我们可以将公共的功能封装在装饰器中,而不是在每个函数中都写一遍。另外,Python装饰器还可以实现函数的缓存、调用次数统计、性能分析等功能。
三、Python装饰器的使用场景
Python装饰器的应用场景非常广泛,下面列举几个常见的使用场景。
1. 日志记录
使用装饰器可以方便地记录函数的调用日志。例如,我们可以定义一个日志装饰器,在调用函数前后输出日志信息:
```
def log(func):
def wrapper(*args, **kwargs):
print(f'[INFO] {func.__name__} is called with {args}, {kwargs}')
value = func(*args, **kwargs)
print(f'[INFO] {func.__name__} returns {value}')
return value
return wrapper
def foo(x, y):
return x + y
debug_foo = log(foo)
print(debug_foo(1, 2))
```
输出结果:
```
[INFO] foo is called with (1, 2), {}
[INFO] foo returns 3
3
```
2. 函数缓存
使用装饰器可以较方便地实现函数缓存的功能,即将函数的输入参数及对应的输出结果缓存下来,下次调用时可以直接返回缓存中的结果。下面是一个简单的缓存装饰器的例子:
```
def cache(func):
memo = {}
def wrapper(*args):
if args in memo:
print(f'[INFO] {func.__name__}({args}) is in cache')
return memo[args]
result = func(*args)
memo[args] = result
print(f'[INFO] {func.__name__}({args}) is not in cache')
return result
return wrapper
def factorial(n):
if n == 0 or n == 1:
return 1
return n * factorial(n - 1)
cached_factorial = cache(factorial)
print(cached_factorial(5)) # calculate
print(cached_factorial(5)) # from cache
```
输出结果:
```
[INFO] factorial((5,)) is not in cache
[INFO] factorial((4,)) is not in cache
[INFO] factorial((3,)) is not in cache
[INFO] factorial((2,)) is not in cache
[INFO] factorial((1,)) is in cache
[INFO] factorial((2,)) is in cache
[INFO] factorial((3,)) is in cache
[INFO] factorial((4,)) is in cache
[INFO] factorial((5,)) is in cache
120
120
```
3. 方法重载
Python中不支持方法重载(Overload),也就是说,不能有两个同名的方法,参数列表不同。但是,使用装饰器,我们可以模拟出方法重载的效果。下面是一个方法重载装饰器的例子:
```
def overload(func):
registry = {}
def register(cls, *args):
def decorator(func):
name = func.__name__
registry[name] = func
return func
class Spam:
@register(int)
def foo(self, x):
return f'foo(int): {x}'
@register(str)
def foo(self, x):
return f'foo(str): {x}'
s = Spam()
print(s.foo(123))
print(s.foo('abc'))
```
输出结果:
```
foo(int): 123
foo(str): abc
```
四、Python装饰器的实现方法
Python装饰器的实现方法有多种,下面介绍两种比较常用的实现:函数装饰器和类装饰器。
1. 函数装饰器
函数装饰器是Python装饰器最常见的实现方法。函数装饰器定义一个函数,它接受一个函数作为参数,并返回一个新的函数。
下面是一个简单的函数装饰器的例子:
```
def my_decorator(func):
def wrapper(*args, **kwargs):
print('Before the function is called.')
result = func(*args, **kwargs)
print('After the function is called.')
return result
return wrapper
def greet(name):
print(f'Hello, {name}.')
greet = my_decorator(greet)
greet('John')
```
输出结果:
```
Before the function is called.
Hello, John.
After the function is called.
```
2. 类装饰器
类装饰器是Python姿势装饰器的一种实现方法。类装饰器定义一个类,它接受一个函数作为参数,并实现__call__方法,以实现对函数的装饰。
下面是一个简单的类装饰器的例子:
```
class my_decorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print('Before the function is called.')
result = self.func(*args, **kwargs)
print('After the function is called.')
return result
def greet(name):
print(f'Hello, {name}.')
greet = my_decorator(greet)
greet('John')
```
输出结果:
```
Before the function is called.
Hello, John.
After the function is called.
```