所不为人知的Python装饰器

装饰器可以说是Python中非常重要的特性之一。有些人要么从没使用过装饰器,要么就是对装饰器的使用一知半解。也有些人觉得装饰器很简单:"装饰器不就是那些把函数作为参数并输出一个函数的函数"。这里介绍一些装饰器“所不为人知”的一些地方。
先回顾一下函数。函数在python中是一等公民,也就是说,函数也是对象,它可以赋值给一个变量、可以作为元素添加到集合对象中、可作为参数值传递给其它函数,还可以当做函数的返回值、也有属性。
例如:
1.1.输出函数f的所有属性
def f():
print('something')
print(dir(f))
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
1.2.赋值给一个变量g
g = f
g()
something
1.3.作为参数传递给其他函数
def func_name(function):
return function.__name__
func_name(f)
f
1.4.作为元素添加到集合对象list中
function_collection = [f, g]
for function in function_collection:
function()
something
something
装饰器常常被描述成“装饰器就是那些把函数作为参数并输出一个函数的函数”,严格地讲,这并不是很准确。其实,他还有如下一些细节:
- 在函数定义的时候就执行了一次装饰器的装饰过程
- 用
@d装饰一个函数定义x,等价于,先定义函数x,然后执行x=d(x) - 用
@d和装饰一个函数定义x,等价于,先定义函数x,然后执行x=e(d(x))@e
举几个例子会更加让人理解。
def print_when_called(function):
def new_function(*args, **kwargs):
print("{} was called".format(function.__name__))
return function(*args, **kwargs)
return new_function def one():
return 1
one = print_when_called(one) @print_when_called
def two():
return 2 [one(), two(), one(), two()]
one was called
two was called
one was called
two was called
[1, 2, 1, 2]
你可能会注意到,上面的输出是在执行[one(), two(), one(), two()]后才打印出来,实际上,在one()或two()执行前,print_when_called就已经返回了负责打印的new_function。下面的例子会更容易理解些:
def print_when_applied(function):
print("print_when_applied was applied to {}".format(function.__name__))
return function @print_when_applied
def never_called():
print("never_called")
print_when_applied was applied to never_called
显而易见,“never_called”没有被执行,但是“print_when_applied was applied to never_called”已经打印出来了。
下面再说一下装饰器执行的顺序。
@print_when_applied
@print_when_called
def this_name_will_be_printed_when_called_but_not_at_definition_time():
pass
this_name_will_be_printed_when_called_but_not_at_definition_time()
print_when_applied was applied to new_function
this_name_will_be_printed_when_called_but_not_at_definition_time was calle
所不为人知的Python装饰器的更多相关文章
- 关于python装饰器
关于python装饰器,不是系统的介绍,只是说一下某些问题 1 首先了解变量作用于非常重要 2 其次要了解闭包 def logger(func): def inner(*args, **kwargs) ...
- python装饰器通俗易懂的解释!
1.python装饰器 刚刚接触python的装饰器,简直懵逼了,直接不懂什么意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍资料,猜有点点开始明白了.总结了一下解释得比较好的,通俗易懂的来说 ...
- Python 装饰器学习
Python装饰器学习(九步入门) 这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 1 2 3 4 5 6 7 8 # -*- c ...
- python 装饰器修改调整函数参数
简单记录一下利用python装饰器来调整函数的方法.现在有个需求:参数line范围为1-16,要求把9-16的范围转化为1-8,即9对应1,10对应2,...,16对应8. 下面是例子: def fo ...
- python 装饰器学习(decorator)
最近看到有个装饰器的例子,没看懂, #!/usr/bin/python class decorator(object): def __init__(self,f): print "initi ...
- Python装饰器详解
python中的装饰器是一个用得非常多的东西,我们可以把一些特定的方法.通用的方法写成一个个装饰器,这就为调用这些方法提供一个非常大的便利,如此提高我们代码的可读性以及简洁性,以及可扩展性. 在学习p ...
- 关于python装饰器(Decorators)最底层理解的一句话
一个decorator只是一个带有一个函数作为参数并返回一个替换函数的闭包. http://www.xxx.com/html/2016/pythonhexinbiancheng_0718/1044.h ...
- Python装饰器由浅入深
装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们 ...
- Python装饰器与面向切面编程
今天来讨论一下装饰器.装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数 ...
随机推荐
- 14、ABPZero系列教程之拼多多卖家工具 新建微信公众号模块
说是模块,其实在MVC中就是区域,新建一个区域专门管理整个微信功能. Web项目新建区域 在Web项目Areas目录下新建一个区域,名称为“Weixin",如下图: 接着打开web.conf ...
- loadrunner中如何将MD5加密的值转换为大写
上篇博客中写过如何将MD5加密,但是我们在实际的测试过程中可能需要将加密的结果进行大小写转换.我在这次的测试过程中就遇见了这样的问题, 我在测试时发现开发人员代码传的sign值是大写,而我加密出来的s ...
- [51nod1232]完美数
如果一个数能够被组成它的各个非0数字整除,则称它是完美数.例如:1-9都是完美数,10,11,12,101都是完美数,但是13就不是完美数(因为13不能被数字3整除). 现在给定正整数x,y,求x和y ...
- 状压dp初探
写了几道状压...然后就一直在颓废... 2064: 分裂 http://www.lydsy.com/JudgeOnline/problem.php?id=2064 初始的为正,最后的为负,假设我们能 ...
- hdu_1711Number Sequence(kmp)
Number Sequence Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- LCS最长公共子序列~dp学习~4
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1513 Palindrome Time Limit: 4000/2000 MS (Java/Others ...
- Logger之Logger.getLogger(CLass)技巧代替system.out.print
---恢复内容开始--- 尊重原创:http://www.cnblogs.com/zxf330301/p/5876117.html 之前一直在使用System.out.println()来调试.但是用 ...
- [20160711][neven代码移植Windows]
相关说明 neven代码用于人脸检测,该代码是从Android源代码中抽取出来的,可以在Linux系统下通过make命令直接进行编译,并且可以通过代码中opencv目录下的测试文件进行测试. 移植环境 ...
- 【转自知乎】:localhost、127.0.0.1 和 本机IP 三者的区别?
作者:知乎用户链接:https://www.zhihu.com/question/23940717/answer/26230963来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注 ...
- Uva 12171 Sculpture - 离散化 + floodfill
题目连接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...