所不为人知的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装饰器与面向切面编程
今天来讨论一下装饰器.装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数 ...
随机推荐
- 认识Sass和Compass
第一章 Sass和Compass让样式表重焕青春 // 内容概要// 开始学习Sass和动态样式表// 用Sass更高效地写样式表// Compass简介// 用Compass迎接工程实践中的样式挑战 ...
- 开发问题(一)在windows和linux端口占用问题
前言 今天在MyEclipse中使用tomcat发现tomcat端口8080竟然被占用了,所以就找了一下解决办法共参考! 在网络程序的调试过程中,经常发生一些出乎意料的事情,比如创建一个TCP服务失败 ...
- [51nod1206]Picture
给你一坨矩形,问这些矩形组成的所有多边形的周长之和. 分别求竖着的边和横着的边. 离散化后线段树,维护当前行(或者列)有多少没在多边形里的,添加矩形就变成添加.删除线段. 每次加线段或删线段时累加一下 ...
- [bzoj3953] [WF2013]Self-Assembly
将正方形视为连接字符间的边.比方说正方形上存在A+,B-,就从A-往B+连边,表示字符可以通过这个正方形进行变换. 如果能构成环的话就可以无穷大了...判环随便写个拓扑什么的... #include& ...
- Codeforces Round #345(Div. 2)-651A.水题 651B.。。。 651C.去重操作 真是让人头大
A. Joysticks time limit per test 1 second memory limit per test 256 megabytes input standard input o ...
- IntelliJ IDEA 配置 smartGit
教你如何在IntelliJ IDEA中配置smartGit? 一.第一种方式: 1.在启动IDEA工具时,点击下拉按钮"Check out from Version Control" ...
- HDU 1233 还是畅通工程(模板——克鲁斯卡尔算法)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1233 题意描述: 输入n个城镇以及n*(n-1)/2条道路信息 计算并输出将所有城镇连通或者间接连通 ...
- (一)surging 微服务框架使用系列之surging 的准备工作rabbitmq安装
(1)下载erlang: http://www.erlang.org/download/otp_win64_17.3.exe 并安装 (2)下载RabbitMQ: http://www.rabbitm ...
- JavaScript八张思维导图—操作符
JS基本概念 JS操作符 JS基本语句 JS数组用法 Date用法 JS字符串用法 JS编程风格 JS编程实践 不知不觉做前端已经五年多了,无论是从最初的jQuery还是现在火热的Angular,Vu ...
- CGI,FAST-CGI,PHP-FPM的区别
http://blog.csdn.net/xsgnzb/article/details/52875331 CGI全称Common Gateway Interface即公共网关接口,它遵循cgi规范,定 ...