聊聊Python装饰器

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装饰器是一个非常有用的特性,它可以用来修改其他函数的功能,而不影响函数本身的结构。装饰器可以用于各种应用,如记录日志、缓存结果、进行身份验证等等,它可以使我们的代码更加简洁、易读、易维护。

免责声明:本文来自互联网,本站所有信息(包括但不限于文字、视频、音频、数据及图表),不保证该信息的准确性、真实性、完整性、有效性、及时性、原创性等,版权归属于原作者,如无意侵犯媒体或个人知识产权,请来电或致函告之,本站将在第一时间处理。猿码集站发布此文目的在于促进信息交流,此文观点与本站立场无关,不承担任何责任。

后端开发标签