Python函数-装饰器:如何在函数前后添加额外功能
Python函数允许通过装饰器(Decorator)在函数前后添加额外的功能,这是 Python 中一个强大且常用的特性。它可以帮助程序员轻松实现常规任务,使代码更加直观、简洁和易于维护。
装饰器是 Python 中一种用来修改其他函数的函数,它定义了一些额外的逻辑代码,并将其绑定到待修饰函数上。它为函数提供了一种非侵入式的修改方法,所以不必直接修改函数的源代码,而是在运行时通过装饰器添加额外的功能。
Python中的装饰器有很多种,下面将介绍其中最常用的几种。
1. 装饰器定义
在Python中,装饰器是以@符号开头的特殊语法。 当 Python 解释器在函数定义时看到@my_decorator 时,它会自动将函数 my_function 作为参数传递给 my_decorator 函数,并将返回值(另一个函数)重新绑定到 my_function 变量上。
@my_decorator
def my_function():
pass
等价于
def my_function():
pass
my_function = my_decorator(my_function)
2. 装饰器示例
下面我们来看一个实际的例子,这个装饰器可以在函数执行前后记录函数的执行时间。
import time
def time_it(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(func.__name__ + " takes " + str((end-start)*1000) + "ms")
return result
return wrapper
@time_it
def my_func():
time.sleep(1)
print("Done")
my_func()
输出结果为:
Done
my_func takes 1000.7638931274414ms
可以看到,my_func() 被修饰器 time_it 包装了起来,函数执行时间被打印出来。
装饰器的作用就体现在能够在函数前后添加新的功能,而不会影响原函数的功能。
3. 带参数的装饰器
装饰器函数可以带不定个数和类型的参数,这样它就可以接收定制不同行为的配置参数。下面我们来看一个带参数的装饰器实例。
def repeat(number=3):
def decorator(func):
def wrapper(*args, **kwargs):
for i in range(number):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(number=4)
def greet(name):
print(f"Hello {name}")
greet("John")
输出结果为:
Hello John
Hello John
Hello John
Hello John
可以看到,函数 greet 被装饰器 repeat 包装了四次,实现了重复输出的功能。
4. 类装饰器
除了函数外,Python还支持类装饰器,类装饰器在修饰类时,将该类的构造函数作为参数交给被装饰器函数。
下面是一个类装饰器的实际例子,它可以为类的所有方法添加日志。
class LogDecorator:
def __init__(self, obj):
self.obj = obj
def __call__(self, *args, **kwargs):
for name, method in self.obj.__dict__.items():
if callable(method):
setattr(self.obj, name, self.__log_decorator(method))
return self.obj
@staticmethod
def __log_decorator(method):
def wrapped(*args, **kwargs):
print(f"Enter into method '{method.__name__}'", args, kwargs)
result = method(*args, **kwargs)
print(f"Exit from method '{method.__name__}'", args, kwargs, result)
return result
return wrapped
@LogDecorator
class Calculator:
def add(self, a, b):
return a + b
def sub(self, a, b):
return a - b
c = Calculator()
print(c.add(1, 2))
print(c.sub(2, 1))
输出结果为:
Enter into method 'add' (1, 2) {}
Exit from method 'add' (1, 2) {} 3
3
Enter into method 'sub' (2, 1) {}
Exit from method 'sub' (2, 1) {} 1
1
可以看到,当我们在定义类 Calculator 时,在其前面加上装饰器 @LogDecorator,就可以为其所有方法添加了日志。
总结
装饰器是 Python 中一个非常重要且实用的特性,它可以避免代码的混乱,使代码更加直观、简洁和易于维护。通过装饰器,我们可以在函数前后添加新的功能,不必修改函数的源代码。 Python 提供了很多种装饰器的实现方法,其中最常用的有带参数的函数装饰器、类装饰器等。 在使用装饰器时,需要注意遵循一些 实践,如不改变函数签名等。
