Python语法详解之decorator装饰器
什么是decorator装饰器
在Python中,decorator是一种特殊的函数,它可以用来修改其他函数的行为。在不改变其他代码的情况下,为一个函数添加新的功能。decorator的核心思想就是:把其他函数作为参数传入,然后在内部加上新的功能,返回新的函数。
使用decorator可以优美地实现以下效果:
- 在不修改原有函数代码的情况下,增加函数的别名、性能分析、计数、缓存功能等。
- 把函数做成类似装饰的外壳,如认证、授权、事务处理、锁定等。
- 嵌套使用多个decorator,模拟装饰器链,可以在函数调用前后进行不同的逻辑处理。
Python中的decorator实现非常优雅,可以用在任何可调用对象上,如函数、方法、类等。
decorator装饰器的基本使用
- 最简单的decorator
```python
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
def say_hello():
print("Hello!")
say_hello = my_decorator(say_hello)
say_hello()
# 输出:
# Something is happening before the function is called.
# Hello!
# Something is happening after the function is called.
```
在上面的代码中,我们定义了一个my_decorator
函数,它获取一个函数作为参数。内部定义了一个wrapper
函数,它向外界提供了一个新的函数接口,包含了原本的函数。在调用原函数之前后,可进行其他处理逻辑。最后,返回修改后的wrapper
函数。
调用原函数的方式:
python
say_hello = my_decorator(say_hello)
say_hello()
在Python中有更加简洁的语法来调用decorator,即使用@decorator_func
进行修饰:
```python
@my_decorator
def say_hello():
print("Hello!")
say_hello()
```
- 带参数的decorator
如果需要给decorator传入参数,需要再添加一层函数嵌套:
```python
def my_decorator_with_args(num):
def inner_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
if num == 0:
print("num is 0")
if num != 0:
func()
print("Something is happening after the function is called.")
return wrapper
return inner_decorator
@my_decorator_with_args(num=2)
def say_hello():
print("Hello!")
say_hello()
```
在上面的代码中,我们定义了一个my_decorator_with_args
函数,它获取一个参数num
,并返回一个decorator函数。decorator将这个参数传递给inner_decorator
函数。
inner_decorator
函数接收原函数,返回一个加上新逻辑的‘wrapper’函数。在decorator中,我们还可以根据num
的取值选择是否执行原函数。
- 类装饰器
在Python中,除了函数装饰器,我们还可以定义类装饰器。类装饰器同样可以用来包装函数或类,类装饰器满足了开闭原则,即对修改封闭,对扩展开放。
```python
class DecoratorClass(object):
def init(self, func):
self.func = func
def call(self, args, kwargs):
print("Something is happening before the function is called.")
self.func(args, **kwargs)
print("Something is happening after the function is called.")
@DecoratorClass
def say_hello():
print("Hello!")
say_hello()
```
示例1:使用decorator装饰函数并缓存结果
from functools import wraps
def memoize(func):
cache = {}
@wraps(func)
def wrapper(*args):
if args in cache:
return cache[args]
else:
result = func(*args)
cache[args] = result
return result
return wrapper
@memoize
def fibonacci(n):
if n in (0, 1):
return n
else:
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(10))
在上面的代码中,我们定义了一个memoize装饰器,用于缓存函数的结果。在wraps函数用于增加函数信息的标注。
使用memoize装饰器对fibonacci函数进行修饰,获取结果时,如果之前已经计算过,则直接返回缓存结果。否则进行计算,返回计算结果,并将结果缓存。
示例2:使用decorator装饰类的方法
class Foo(object):
@staticmethod
@print_args
def bar(*args, **kwargs):
print(args, kwargs)
def print_args(func):
def wrapper(*args, **kwargs):
print("Arguments:", args, kwargs)
return func(*args, **kwargs)
return wrapper
foo = Foo()
foo.bar(1, 2, 3, a=4, b=5)
在上面的代码中,我们定义了一个Foo类,其中包含一个bar方法。我们使用print_args装饰器对这个方法进行修饰,修饰后在函数执行之前,打印出函数通过参数传递过来的参数值。
最后,我们创建一个Foo实例,然后调用这个实例中的bar方法,实际上调用的是被修饰后的bar方法。修饰后的bar方法执行之前,会打印出函数参数的信息,并将参数传递给原始的bar方法,最后打印出bar方法返回的结果。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python语法详解之decorator装饰器 - Python技术站