Python基础 装饰器及练习

一、Python装饰器概览

Python装饰器是Python编程中一个非常强大的概念,它提供了一种灵活的方式来修改或扩展函数或类的行为。装饰器常用于添加或修改函数或方法的功能,比如缓存、计时器、日志记录等。装饰器也大大简化了代码重复度,增强了代码的可读性和可维护性。

1.1 装饰器的定义

装饰器(Decorator)是一种很简单但是非常重要的设计模式。它可以动态地给一个对象添加一些额外的功能,而不会修改这个对象的源代码。

1.2 装饰器的作用

Python装饰器主要用于以下方面:

- 动态地给某个函数或方法添加功能,而不改变其原有的定义和调用方式;

- 减少重复的代码,增强代码可读性和可维护性。

1.3 装饰器的特点

Python装饰器有以下几个特点:

- 装饰器本身就是一个函数或类;

- 装饰器可以接受其他的函数或类作为参数;

- 装饰器还可以返回一个函数或类作为输出。

1.4 装饰器的语法

Python装饰器的语法格式如下:

@decorator

def function():

pass

上面的代码中,@decorator是一个装饰器,可以接受一个函数作为参数,并返回另外一个函数。函数function被装饰器修饰后,会在调用时自动添加上一些额外的功能。

1.5 装饰器的分类

Python装饰器一般分为以下几类:

- 类装饰器

- 函数装饰器

- 参数化装饰器

二、Python装饰器实例

下面我们通过实例来了解Python装饰器的具体使用。

首先我们定义一个装饰器log,它可以在函数调用前后打印出函数的名称和参数:

def log(func):

def wrapper(*args, **kw):

print('调用函数 %s():' % func.__name__)

func(*args, **kw)

print('调用结束!')

return wrapper

在定义了log装饰器后,我们可以使用@log来使用它:

@log

def now():

print('2022-3-2')

我们来分析一下这段代码的实现过程。在使用@log来修饰函数now()时,Python解释器会自动把下面的语句:

now = log(now)

转换成这样的语句:

now = log(now)

也就是说,now函数会被包装成wrapper函数。当我们调用now()函数时,实际上执行的是wrapper()函数,wrapper()函数会在调用now()函数前后分别打印出调用信息。

三、参数化装饰器

除了定义简单的装饰器外,我们还可以定义带参数的装饰器。带参数的装饰器主要用于为不同的对象添加不同的功能。

def log(prefix):

def decorator(func):

def wrapper(*args, **kw):

print('%s %s():' % (prefix, func.__name__))

return func(*args, **kw)

return wrapper

return decorator

上述代码中,定义了一个装饰器log,它可以指定打印的前缀信息。在使用这个带参数的装饰器时,需要使用两级嵌套的装饰器。

首先需要使用log('execute')来创建一个装饰器,然后使用这个装饰器来修饰函数:

@log('execute')

def now():

print('2022-3-2')

这时调用now()函数,会在控制台输出执行信息:

execute now():

2022-3-2

四、实战练习

下面我们来看一个实战练习,练习内容是编写一个能够缓存函数结果的装饰器。

我们可以定义一个带参数的缓存装饰器,它会在内存中缓存函数的结果,如果下次再次调用函数时,会直接返回结果,而不是重新计算。缓存的数据可以定期清除,避免占用过多内存。

import time

from functools import wraps

def cache(seconds):

def _cache(func):

@wraps(func)

def wrapper(*args, **kwargs):

key = str(args) + str(kwargs)

if cache.has_key(key) and (time.time() - cache[key]['time']) < seconds:

print('hit cache')

return cache[key]['result']

result = func(*args, **kwargs)

cache[key] = {'time': time.time(), 'result': result}

return result

return wrapper

return _cache

cache.has_key = lambda key: key in cache

@cache(seconds=5)

def fib(n):

if n < 2:

return n

return fib(n-1) + fib(n-2)

print(fib(8))

print(fib(8))

time.sleep(6)

print(fib(8))

print(fib(8))

上述代码中,使用了Python内置的functools.wraps装饰器来保持被修饰函数的元信息(如函数名、参数、注释等)。当函数被重新赋值后,这些元信息会丢失。使用wraps装饰器来修饰wrapper函数,可以解决该问题。

五、总结

Python装饰器是Python编程中一个重要的概念,它可以动态地给一个对象添加一些额外的功能,而不需要修改这个对象的源代码。Python装饰器有非常灵活的应用场景,可以用于函数和类的定义、参数检查、性能优化等方面。在实际应用中,建议掌握不同类型的装饰器(如类装饰器、函数装饰器、参数化装饰器)以及装饰器的用法和语法规则,这会大大提高Python编程的效率和可读性。

后端开发标签