所不为人知的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装饰器与面向切面编程
今天来讨论一下装饰器.装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数 ...
随机推荐
- CTF---密码学入门第六题 古典密码
古典密码分值:10 来源: 北邮天枢战队 难度:易 参与人数:5115人 Get Flag:1549人 答题人数:1783人 解题通过率:87% 密文内容如下{79 67 85 123 67 70 8 ...
- Codefoces 723A The New Year: Meeting Friends
A. The New Year: Meeting Friends time limit per test:1 second memory limit per test:256 megabytes in ...
- AtCoder Grand Contest 016
在雅礼和衡水的dalao们打了一场atcoder 然而窝好菜啊…… A - Shrinking 题意:定义一次操作为将长度为n的字符串变成长度n-1的字符串,且变化后第i个字母为变化前第i 或 i+1 ...
- 构建LVS-DR+Keepalive高可用集群
------client----------主LVS----------从LVS------------WEB1-------------WEB2--------- 2.2.2.250 2.2.2. ...
- 一 : springmvc常用注解
springmvc常用注解详解1.@Controller在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层 ...
- 什么是MVC ?
记得第一次面试phper(php是对我来说可以快速上手的另一web开发语言),人家问我MVC,我只知道m就是model,v就是view,c就是Controller,具体把其它的认识我是一无所知,结果我 ...
- nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address
http://blog.csdn.net/ownfire/article/details/7966645 今天在做LNMP的时候,启动nginx服务,无法开启,导致网页打不开.把服务从起一下发现提示错 ...
- vue-cli的webpack模版项目配置解析-build/dev-server.js
我们在使用vue-cli搭建vuejs项目(Vuejs实例-01使用vue-cli脚手架搭建Vue.js项目)的时候,会自动生成一系列文件,其中就包含webpack配置文件.我们现在来看下,这些配置到 ...
- Varnish的vcl子程序
Varnish的VCL子程序 以下内容参考: http://book.varnish-software.com/4.0/ VCL子进程,在其中定制Varnish的行为.VCL子例程可用于:添加自定义标 ...
- jquery checkbox 全选反选代码只能执行一遍,第二次就失败
遇到问题背景: 在写到购物车的全选交互的时候,商品选中的状态只有在第一次的时候可以,第二次就无法选中:(代码如下) $(".chooseall").click(function() ...