持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第16天,点击查看活动详情
前言
说说对Python装饰器的理解,相信是很多人在面试中会遇到的问题。你可能会说,装饰器是Python一种语法糖的形式,可以放在其他函数前,这样起到不改代码增加额外功能。这样说是对的,这篇我们往细里说,看看装饰器是如何使用的。
装饰器的定义
装饰器在本质上还是一个函数,也就是我们熟知的闭包,装饰器的返回值也是一个函数对象。在Python中装饰器应用场景有很多,比如说日志的插入操作、权限校验等。
装饰器的基本写法
装饰器有很多种写法,首先我们来看看最基本的一种写法:
import time
def cost_time(func):
def wrapper():
st = time.time()
func()
et = time.time()
c_t = et - st
print('本次调用用时{}'.format(c_t))
return wrapper
# 使用装饰器
@cost_time
def test():
print('测试一下啦')
time.sleep(3)
test()
例子很简单,装饰器的功能是打印一个函数的执行时间。来看看结果,打印出了具体耗时。
In [7]: test()
测试一下啦
本次调用用时3.004469156265259
装饰器能带参数吗
装饰器能带参数吗?答案是可以的。带参数的场景有2种:
- 一种是装饰器本身带参数
- 另一种是装饰器中获取被装饰函数的参数
装饰器本身带参数
在有些场景,我们需要在装饰器中带某些参数。比如需要待根据参数来执行不同代码,就需要获取参数了。使用方法也很简单,看例子:
def dec(animal):
def print_dec(func):
def wrapper(*args, **kwargs):
func(*args)
if animal == "猫":
msg = "喵喵喵"
elif animal == "狗":
msg = "汪汪汪"
print(msg)
return wrapper
return print_dec
@dec("猫")
def cat_yell():
print("我是猫")
@dec("狗")
def dog_yell():
print("我是狗")
cat_yell()
dog_yell()
具体写法就是将装饰器再嵌套一层,在最外层获取参数,然后在被装饰函数外调用装饰器时将参数带上。
装饰器获取被装饰函数的参数
获取被装饰函数的参数,可通过args和kwargs来获取。直接看例子再讲解:
def dec(func):
def wrapper(*args, **kwargs):
print(*args)
print(**kwargs)
return func(*args, **kwargs)
return wrapper
@dec
def test(a, b):
print("位置参数")
@dec
def test_1(a=1,b=2):
print("关键字参数")
test(1, 2)
test_1(3, 4)
传参方式可以是位置参数,也可以是关键字参数。在装饰器内用*args、 **kwargs来接收即可。
小结
Python装饰器在生产中应用非常广泛,我们可以在很多需要附加功能的地方使用到。当然一个函数中也可同时使用多个装饰器,装饰器的调用顺序是需要注意的。