python带参数装饰器用法,三点水的女孩名字大全,女孩起名技巧有哪些

今天来说说 Python 里的装饰器 (decorator)。它不难,但却几乎是 “精通” Python 的路上的第一道关卡。让我们来看看它到底是什么东西,为什么我们需要它。

手写装饰器

现在我们要写一个函数:

def add(x, y=10):return x + y

然后我们想看看运行的结果,于是写了几个 print 语句:

print("add(10)", add(10))print("add(20, 30)", add(20, 30))print("add('a', 'b')", add('a', 'b'))# Results:# add(10) 20# add(20, 30) 50# add('a', 'b') ab

现在我们想看看测试这个函数的性能,于是我们加上这个代码:

from time import timebefore = time()print("add(10)", add(10))after = time()print("time taken: {}".format(after - before))before = time()print("add(20, 30)", add(20, 30))after = time()print("time taken: {}".format(after - before))before = time()print("add('a', 'b')", add('a', 'b'))after = time()print("time taken: {}".format(after - before))# Results# add(10) 20# time taken: 0.00017189979553222656# add(20, 30) 50# time taken: 9.751319885253906e-05# add('a', 'b') ab# time taken: 0.00012969970703125

代码马上变得很复杂。但最重要的是,我们得写一堆代码(复制粘贴),程序员是懒惰的,所以我们就想到一些更简单的方法,与其写这么多次,我们可以只写一次代码:

from time import timedef add(x, y=10):before = time()result = x + yafter = time()print('elapsed: ', after - before)return resultprint("add(10)", add(10))print("add(20, 30)", add(20, 30))print("add('a', 'b')", add('a', 'b'))# Results# elapsed:1.9073486328125e-06# add(10) 20# elapsed:9.5367431640625e-07# add(20, 30) 50# elapsed:1.9073486328125e-06# add('a', 'b') ab

不论是代码的修改量还是代码的美观程度,都比之前的版本要好!

但是,现在我们写了另一个函数:

def sub(x, y=10):return x - y

我们必须再为 sub 函数加上和 add 相同的性能测试代码:

def sub(x, y=10):before = time()result = x - yafter = time()print('elapsed: ', after - before)return result

作为一个懒惰的程序员,我们立马就发现了,有一个 “模式” 反复出现,即执行一个函数,并计算这个函数的执行时间。于是我们就可以把这个模式抽象出来,用函数:

from time import timedef timer(func, x, y = 10):before = time()result = func(x, y)after = time()print("elapsed: ", after - before)return resultdef add(x, y = 10):return x + ydef sub(x, y = 10):return x - yprint("add(10)", timer(add, 10))print("add(20, 30)", timer(add, 20, 30))

但这样还是很麻烦,因为我们得改到所有的测试用例,把 add(20, 30) 改成timer(add, 20, 30)。于是我们进一步改进,让 timer 返回函数:

def timer(func):def wraper(x, y=10):before = time()result = func(x, y)after = time()print("elapsed: ", after - before)return resultreturn wraperdef add(x, y = 10):return x + yadd = timer(add)def sub(x, y = 10):return x - ysub = timer(sub)print("add(10)", add(10))print("add(20, 30)", add(20, 30))

这里的最后一个问题是,我们的 timer 包装的函数可能有不同的参数,于是我们可以进一步用 *args, **kwargs 来传递参数:

def timer(func):def wraper(*args, **kwargs):before = time()result = func(*args, **kwargs)after = time()print("elapsed: ", after - before)return resultreturn wraper

这里的 timer 函数就是一个 “装饰器”,它接受一个函数,并返回一个新的函数。在装饰器的内部,对原函数进行了“包装”。

注:上面的例子取自 What Does it Take to Be an Expert At Python。

@ 语法糖

上一节是一个懒惰的程序员用原生的 Python 写的装饰器,但在装饰器的使用上,用的是这个代码:

def add(x, y = 10):return x + yadd = timer(add)# >> add.__name__wrapper>>> help(add)Help on function wraper in module __main__:wraper(*args, **kwargs)

可以看到被装饰的函数,名称变成了装饰器返回的函数名 wraper,这对于函数的使用者来说很不方便。于是我们需要修改装饰器,保留原函数的名称:

def timer(func):def wraper(*args, **kwargs):before = time()result = func(*args, **kwargs)after = time()print("elapsed: ", after - before)return resultwraper.__name__ = func.__name__# > add.__name__add>>> help(add)Help on function add in module __main__:add(*args, **kwargs)Add two numbers

当然,函数的信息除了 __name__ 与 __doc__ 外,还有 __module__,__qualname__ 等,每次都手写很浪费时间。Python 提供了内置的装饰器 wraps 来装饰返回的函数:

from functools import wrapsdef timer(func):@wraps(func) #
python基础之带参数装饰器和迭代器 - 菜鸟学院python怎么实现带参数的装饰器-百度经验Python进阶(七)----带参数的装饰器,多个装饰器修饰同一个函数 ...一些关于python 装饰器的个人理解 - html中文网python装饰器带参数函数 - CSDNpython带参数装饰器 - CSDNPython Decorator(装饰器) | 三点水Python装饰器,读完这篇你就懂了 - 掘金如何更通俗地讲解Python的装饰器? - 知乎Python 装饰器原理、定义与用法详解python中的装饰器是干嘛的-Python装饰器的基本概念和用法Python装饰器高级版—Python类内定义装饰器并传递self参数Python---装饰器关键字参数python中的装饰器是干嘛的-简单说明Python中的装饰器用法Python装饰器的另类用法python装饰器类-Python 装饰器装饰类中的方法python--装饰器参数检查python装饰器及functools模块python中的函数装饰器和类装饰器作用实现方法和应用场景python3之装饰器(类装饰器)实现 下篇python 装饰器 参数-python函数装饰器之带参数的函数和带参数装饰器用法示例...自动化测试python装饰器使用python 装饰器使用_为什么要使用Python装饰器python GUI库图形界面开发之PyQt5信号与槽的高级使用技巧装饰器信号与槽详细使用方法与实例python装饰器和函数装饰器区别_python装饰器用法5分钟掌握 Python 中的装饰器python装饰器在类中使用-python-使用类作为方法装饰器一起来理解Python中的装饰器的本质validoot:使用函数装饰器方法参数进行简单验证的 Python 模块-源码
underway中文attempt中文蒜蓉小青菜蒜蓉小青菜的家常做法蒜蓉空心菜做法小米扫地机器人改装拖地小米扫地机器人拖地走不动命令方块弄附魔金苹果故宫首饰图片大全500万比分防弹少年团回归2020三国杀名将传活动开启表三国杀名将活动表图片日娱之我全都要书单书评微擎系统网站搭建视频教程起名属水13画的字有?一般将来时时间标志词坊间故事坑爹游戏结局宋杨身份习大大在93大阅兵上的讲话原文外教网高考语文作文素材优美语段积累豆腐鸡蛋炒韭菜韭菜豆腐馅饺子窍门