优草派  >   Python

简单上手Python中装饰器的使用

刘婷婷            来源:优草派

Python中的装饰器是一种很有用的语法,它可以使我们在不改变函数代码的情况下对其进行扩展和修改。但是,对于初学者来说,装饰器的概念可能比较抽象,很难理解和上手。本文将从多个角度为大家详细介绍Python中装饰器的使用。

一、装饰器的基本概念

简单上手Python中装饰器的使用

装饰器的本质是一个函数,它可以接收一个函数作为参数,然后返回一个新的函数。通过这种方式,我们可以在不改变原函数的情况下对其进行扩展和修改。下面是一个简单的装饰器示例:

```

def decorator(func):

def wrapper():

print("Before function is called.")

func()

print("After function is called.")

return wrapper

@decorator

def my_function():

print("Hello, world!")

my_function()

```

这段代码定义了一个装饰器函数`decorator`,它接收一个函数`func`作为参数,然后定义了一个内部函数`wrapper`,在`wrapper`中先输出一些信息,然后调用`func`,最后再输出一些信息。在这个例子中,我们使用了`@decorator`语法糖来将`my_function`函数装饰了起来。当我们调用`my_function`时,实际上调用的是`wrapper`函数,从而实现了在函数调用前后输出一些信息的目的。

二、装饰器的应用场景

装饰器的应用场景非常广泛,下面列举了几个比较常见的应用场景。

1. 记录函数的运行时间

我们可以定义一个装饰器函数,用来记录函数的运行时间。下面是一个简单的示例:

```

import time

def timer(func):

def wrapper(*args, **kwargs):

start_time = time.time()

result = func(*args, **kwargs)

end_time = time.time()

print("Function {} took {} seconds to run.".format(func.__name__, end_time - start_time))

return result

return wrapper

@timer

def my_function():

time.sleep(2)

my_function()

```

在这个例子中,我们定义了一个装饰器函数`timer`,它接收一个函数`func`作为参数,并定义了一个内部函数`wrapper`。在`wrapper`中先记录下当前时间,然后调用`func`,最后再记录下当前时间,并输出函数运行的时间。当我们使用`@timer`语法糖来将`my_function`函数装饰时,就可以自动记录函数的运行时间了。

2. 验证用户身份

我们可以定义一个装饰器函数,用来验证用户的身份。下面是一个简单的示例:

```

users = {

"Alice": "password1",

"Bob": "password2",

"Charlie": "password3"

}

def authenticate(func):

def wrapper(*args, **kwargs):

username = input("Enter your username: ")

password = input("Enter your password: ")

if username in users and users[username] == password:

return func(*args, **kwargs)

else:

print("Access denied.")

return wrapper

@authenticate

def my_function():

print("Hello, world!")

my_function()

```

在这个例子中,我们定义了一个装饰器函数`authenticate`,它接收一个函数`func`作为参数,并定义了一个内部函数`wrapper`。在`wrapper`中首先要求用户输入用户名和密码,然后根据用户输入的信息验证用户身份。如果验证通过,则调用`func`,否则输出“Access denied.”。当我们使用`@authenticate`语法糖来将`my_function`函数装饰时,就可以自动验证用户身份了。

3. 缓存函数的计算结果

我们可以定义一个装饰器函数,用来缓存函数的计算结果。下面是一个简单的示例:

```

cache = {}

def memoize(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))

```

在这个例子中,我们定义了一个全局变量`cache`,用来保存函数的计算结果。我们还定义了一个装饰器函数`memoize`,它接收一个函数`func`作为参数,并定义了一个内部函数`wrapper`。在`wrapper`中首先检查缓存中是否已经有了当前参数的计算结果,如果有则直接返回结果,否则调用`func`进行计算,并将结果保存到缓存中。当我们使用`@memoize`语法糖来将`fibonacci`函数装饰时,就可以自动缓存函数的计算结果了。

三、装饰器的高级应用

除了上面介绍的应用场景外,装饰器还有很多高级应用。下面列举了几个比较常见的高级应用。

1. 带参数的装饰器

装饰器不仅可以接收函数作为参数,还可以接收其他参数。下面是一个带参数的装饰器示例:

```

def repeat(num):

def decorator(func):

def wrapper(*args, **kwargs):

for i in range(num):

func(*args, **kwargs)

return wrapper

return decorator

@repeat(3)

def my_function():

print("Hello, world!")

my_function()

```

在这个例子中,我们定义了一个带参数的装饰器函数`repeat`,它接收一个参数`num`,并返回一个装饰器函数。装饰器函数接收一个函数`func`作为参数,并定义了一个内部函数`wrapper`。在`wrapper`中循环调用`func`,次数为`num`。当我们使用`@repeat(3)`语法糖来将`my_function`函数装饰时,就可以让`my_function`函数重复执行3次了。

2. 使用类来定义装饰器

装饰器不仅可以使用函数来定义,还可以使用类来定义。下面是一个使用类来定义装饰器的示例:

```

class Decorator:

def __init__(self, func):

self.func = func

def __call__(self, *args, **kwargs):

print("Before function is called.")

self.func(*args, **kwargs)

print("After function is called.")

@Decorator

def my_function():

print("Hello, world!")

my_function()

```

在这个例子中,我们定义了一个类`Decorator`,它接收一个函数`func`作为参数,并重写了`__call__`方法。在`__call__`方法中先输出一些信息,然后调用`func`,最后再输出一些信息。当我们使用`@Decorator`语法糖来将`my_function`函数装饰时,实际上是创建了一个`Decorator`对象,并将`my_function`函数作为参数传递给它。

3. 多个装饰器的组合

我们可以将多个装饰器组合起来使用。下面是一个示例:

```

def decorator1(func):

def wrapper():

print("Decorator 1 before function is called.")

func()

print("Decorator 1 after function is called.")

return wrapper

def decorator2(func):

def wrapper():

print("Decorator 2 before function is called.")

func()

print("Decorator 2 after function is called.")

return wrapper

@decorator1

@decorator2

def my_function():

print("Hello, world!")

my_function()

```

在这个例子中,我们定义了两个装饰器函数`decorator1`和`decorator2`,它们都接收一个函数`func`作为参数,并定义了一个内部函数`wrapper`。在`wrapper`中先输出一些信息,然后调用`func`,最后再输出一些信息。当我们使用`@decorator1`和`@decorator2`语法糖来将`my_function`函数装饰时,实际上是先将`my_function`函数传递给`decorator2`进行装饰,然后再将装饰后的函数传递给`decorator1`进行装饰。

四、

【原创声明】凡注明“来源:优草派”的文章,系本站原创,任何单位或个人未经本站书面授权不得转载、链接、转贴或以其他方式复制发表。否则,本站将依法追究其法律责任。
TOP 10
  • 周排行
  • 月排行