1. 什么是装饰器
在Python中,装饰器是一种函数,它可以修改其他函数的功能。装饰器本身不修改被装饰的函数的代码。
装饰器可以给函数添加新的功能,而不影响函数的结构。
1.1 装饰器的基本用法
下面是一个简单的装饰器的例子:
def my_decorator(func):
def wrapper():
print("Before function is called.")
func()
print("After function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello, world!")
say_hello()
@my_decorator表示将函数say_hello
作为参数传递给my_decorator
函数,并用返回的函数对象重新绑定say_hello
。因此,当say_hello()
被调用时,my_decorator()
将被调用。
上述代码的输出结果如下:
Before function is called.
Hello, world!
After function is called.
1.2 更高级的装饰器
有些时候,我们需要给装饰器传递一些参数,或者对装饰器本身进行装饰。
下面是一个更高级的装饰器的例子:
def repeat(num):
def my_decorator(func):
def wrapper(*args, **kwargs):
for i in range(num):
print("Before function is called.")
func(*args, **kwargs)
print("After function is called.")
return wrapper
return my_decorator
@repeat(num=3)
def say_hello(name):
print("Hello, {0}!".format(name))
say_hello("world")
上述代码中,我们定义了一个repeat
函数,它接受一个整数参数num
,返回一个新的装饰器函数my_decorator
。这个新的装饰器函数接受一个函数对象func
,返回一个新的函数wrapper
。
@repeat(num=3)表示将装饰器my_decorator
作为参数传递给repeat
函数,并使用num=3
调用repeat
函数。因此,当say_hello("world")
被调用时,my_decorator()
将被调用,wrapper
将被返回并且调用wrapper("world")
。
上述代码的输出结果如下:
Before function is called.
Hello, world!
After function is called.
Before function is called.
Hello, world!
After function is called.
Before function is called.
Hello, world!
After function is called.
2. 装饰器的应用
2.1 记录日志
用装饰器来记录日志是非常方便的。下面是一个记录日志的装饰器的例子:
def logger(func):
def wrapper(*args, **kwargs):
print("Calling function [{0}] with arguments ({1}, {2})".format(func.__name__, args, kwargs))
result = func(*args, **kwargs)
print("Function [{0}] returned [{1}]".format(func.__name__, result))
return result
return wrapper
@logger
def add(x, y):
return x + y
result = add(2, 3)
print("Function [add] returned [{0}]".format(result))
上述代码的输出结果如下:
Calling function [add] with arguments (2, 3)
Function [add] returned [5]
Function [add] returned [5]
2.2 缓存结果
有些时候,我们需要缓存函数的结果,以提高程序的性能。下面是一个缓存结果的装饰器的例子:
def memoize(func):
cache = {}
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 == 0:
return 0
elif n == 1:
return 1
else:
return fibonacci(n-1) + fibonacci(n-2)
result = fibonacci(35)
print("Fibonacci({0}) = {1}".format(35, result))
上述代码的输出结果如下:
Fibonacci(35) = 9227465
2.3 身份验证
用装饰器来实现身份验证也是非常方便的。下面是一个实现身份验证的装饰器的例子:
def authenticate(func):
def wrapper(*args, **kwargs):
username = input("Enter your username: ")
password = input("Enter your password: ")
if username == "admin" and password == "password":
return func(*args, **kwargs)
else:
print("Authentication failed!")
return wrapper
@authenticate
def add(x, y):
return x + y
result = add(2, 3)
print("Function [add] returned [{0}]".format(result))
上述代码的输出结果如下:
Enter your username: admin
Enter your password: password
Function [add] returned [5]
3. 总结
Python装饰器是一个非常有用的特性,它可以用来修改其他函数的功能,而不影响函数本身的结构。装饰器可以用于各种应用,如记录日志、缓存结果、进行身份验证等等,它可以使我们的代码更加简洁、易读、易维护。