浅谈python装饰器探究与参数的领取


Posted in Python onDecember 01, 2017

首先上原文:

现在,假设我们要增强now()函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。

本质上,decorator就是一个返回函数的高阶函数。

Decorator本质是高阶函数?

不信邪的我试了下..

def g():
 print("这里是G")
 return "G"

@g
def f():
 print("这里是F")
 return 1
'''
--------------------------------------------
line 5, in <module>
 @g
TypeError: g() takes 0 positional arguments but 1 was given
>>>
'''

运行结果在注释里

尴尬了...g被强制塞了个参数,那个参数应该是g"修饰的对象"

修改下继续.....

def g(f):
 print("这里是G")
 return "G"

@g
def f():
 print("这里是F")
 return 1
'''
--------------------------------------------
这里是G
>>> f()
Traceback (most recent call last):
 File "<pyshell#0>", line 1, in <module>
 f()
TypeError: 'str' object is not callable
'''

str对象不能被调用,,,这里的str只有一个,就是g的返回值

为了验证下,我把"G"改成了2

结果是

TypeError: 'int' object is not callable

OK了,大概意思就是,装饰器首先被"塞"一个参数,然后,返回值还要被调用一次,然而好像只有函数才能被调用,,所以,为了不报错,装饰器必须返回一个函数,装饰器必须是高阶函数......

我表示不服( ̄へ ̄),不就是函数吗,g的参数就是函数,,,骚操作上脑ing

def g(f):
 print("这里是G")
 return f

@g
def f():
 print("这里是F")
 return 1
'''
--------------------------------------------
这里是G
>>> f()
这里是F
'1'
'''

运行成功.但是....说好的"打印日志功能"呢,#没错"这里是G"就是我想要的日志

疑点一: 打印的"这里是G"是第一行,是在输入"f()"之前发生的....

疑点二: 输入"f()"后,"这里是G"没打出来.....

#单看g函数,它不算是"高阶函数"

作为成功的例子,它太失败了┐( ̄ヘ ̄)┌

##好吧,我投降了,负隅顽抗也不怎么有意思.....

闭包告诉我们一个道理,,,为了保证返回值一定是函数,最好的措施就是"在函数内部,现场造一个函数然后扔出去"

def g(f):
 print("这里是G")
 def h():
  print('这里是H')
  return "H"
 return h

@g
def f():
 print("这里是F")
 return 1
'''
--------------------------------------------
这里是G
>>> f()
这里是H
'H'
>>> f()
这里是H
'H'
>>> 
'''

f函数不执行了,,是的没错,我还多试了一次的

另外,两条日志只有里面的能用......(下文会解释的)

看了一下书,h函数返回f()的话,f函数就能被执行了,,,,,个人感觉装饰器应该叫"劫持器"

def g(f):
 print("这里是G")
 def h():
  print('这里是H')
  return f()
 return h

@g
def f():
 print("这里是F")
 return 1
'''
--------------------------------------------
这里是G
>>> f()
这里是H
这里是F
'1'
>>> f
<function g.<locals>.h at 0x0000020CBDBB6C80>
'''

按书上的思路解释下

'''
@g
def f():
 pass
>>>f()
等价于
>>>g(f) ()
g函数执行,返回
>>>h ()
h函数执行(打印日志)
>>>f()
f执行,返回1
>>>1
'''

加上参数,

def g(f):
 print("这里是G")
 def h(*args,**kw):
  print('这里是H')
  return f(*args,**kw)
 return h

@g
def f(*args,**kw):
 print("这里是F")
 return "1"
'''
>>>f(*args,**kw)
等价于
>>>g(f) (*args,**kw)
g函数执行,返回
>>>h (*args,**kw)
h函数执行(打印日志)
>>>f(*args,**kw)
f执行,返回1
>>>1
'''

可以看出,(*args,**kw)本改被h函数拿走,所以,观察h函数,h把它的参数原封不动的交给了f

机智的我动了歪主意

def g(f):
 print("这里是G")
 def h():#h没要求参数
  print('这里是H')
  return f
 return h

@g
def f(*args,**kw):
 print("这里是F")
 return "1"
'''
>>>f()(*args,**kw)
等价于
>>>g(f) ()(*args,**kw)
g函数执行,返回
>>>h ()(*args,**kw)
h函数执行,h拿的空参数
(打印日志)
>>>f(*args,**kw)
f执行,返回1
>>>1
'''

可是新的问题来了,后面f调用的时候得多加个空括号,否则

'''
>>>f(*args,**kw)
等价于
>>>g(f) (*args,**kw)
g函数执行,返回
>>>h (*args,**kw)
h函数执行(打印日志)返回f
>>>f
这是一个函数对象
'''

以上告诉我们一个道理"函数执行不执行取决于后面有没有括号"

举个例子

def m(a):
 print(a)
 return m

print(m(1)(2)(3)(4)(5)(6)(7)(8)(9)(10))
'''
-----------------------------
2
4
6
8
10
<function m at 0x000002832BDB10D0>

烧脑时刻

f = a.b.c()()[0]()[d()()[e]]

a模块的b类的c方法是高阶函数,最终返回一个列表,列表里有个函数

函数又返回一个字典............

以上这篇浅谈python装饰器探究与参数的领取就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python和php通信乱码问题解决方法
Apr 15 Python
分析Python的Django框架的运行方式及处理流程
Apr 08 Python
浅析Python中的多条件排序实现
Jun 07 Python
python用post访问restful服务接口的方法
Dec 07 Python
Django url,从一个页面调到另个页面的方法
Aug 21 Python
OpenCV模板匹配matchTemplate的实现
Oct 18 Python
详解PyQt5信号与槽的几种高级玩法
Mar 24 Python
python操作微信自动发消息的实现(微信聊天机器人)
Jul 14 Python
Python实现Canny及Hough算法代码实例解析
Aug 06 Python
python 制作磁力搜索工具
Mar 04 Python
pytorch训练神经网络爆内存的解决方案
May 22 Python
Python 使用 Frame tkraise() 方法在 Tkinter 应用程序中的Frame之间切换
Apr 24 Python
Python简单读取json文件功能示例
Nov 30 #Python
Python实现嵌套列表及字典并按某一元素去重复功能示例
Nov 30 #Python
Python实现的多线程同步与互斥锁功能示例
Nov 30 #Python
Python实现按特定格式对文件进行读写的方法示例
Nov 30 #Python
[原创]教女朋友学Python3(二)简单的输入输出及内置函数查看
Nov 30 #Python
Python爬虫实现爬取京东手机页面的图片(实例代码)
Nov 30 #Python
Python编程使用tkinter模块实现计算器软件完整代码示例
Nov 29 #Python
You might like
Breeze 文章管理系统 v1.0.0正式发布
2006/12/14 PHP
php微信公众平台开发之获取用户基本信息
2015/08/17 PHP
php连接MSsql server的五种方法总结
2018/03/04 PHP
js文本框输入点回车触发确定兼容IE、FF等
2013/11/19 Javascript
javascript跨浏览器的属性判断方法
2014/03/16 Javascript
基于jQuery实现的图片切换焦点图整理
2014/12/07 Javascript
Node.js 异步编程之 Callback介绍(一)
2015/03/30 Javascript
JavaScript中的Math.LN2属性用法详解
2015/06/12 Javascript
利用node.js本地搭建HTTP服务器
2017/04/19 Javascript
详解Node项目部署到云服务器上
2017/07/12 Javascript
jQuery实现的文字逐行向上间歇滚动效果示例
2017/09/06 jQuery
nodejs+express搭建多人聊天室步骤
2018/02/12 NodeJs
浅谈Node.js 沙箱环境
2018/05/15 Javascript
基于JavaScript实现控制下拉列表
2020/05/08 Javascript
angular8.5集成TinyMce5的使用和详细配置(推荐)
2020/11/16 Javascript
Python正则表达式介绍
2012/08/06 Python
Python语言编写电脑时间自动同步小工具
2013/03/08 Python
Python urllib模块urlopen()与urlretrieve()详解
2013/11/01 Python
跟老齐学Python之从if开始语句的征程
2014/09/14 Python
对Python中Iterator和Iterable的区别详解
2018/10/18 Python
python打开使用的方法
2019/09/30 Python
python3.7将代码打包成exe程序并添加图标的方法
2019/10/11 Python
如何获取Python简单for循环索引
2019/11/21 Python
浅谈cv2.imread()和keras.preprocessing中的image.load_img()区别
2020/06/12 Python
Abe’s of Maine:自1979以来销售相机和电子产品
2016/11/21 全球购物
澳大利亚头发和美容产品购物网站:OZ Hair & Beauty
2020/03/27 全球购物
MVC的各个部分都有那些技术来实现?如何实现?
2016/04/21 面试题
珍惜水资源建议书
2014/03/12 职场文书
践行党的群众路线心得体会
2014/11/05 职场文书
旷工检讨书1000字
2015/01/01 职场文书
小学教师个人总结
2015/02/05 职场文书
老乡聚会通知
2015/04/23 职场文书
初中家长意见
2015/06/03 职场文书
同学聚会致辞集锦
2015/07/28 职场文书
校长新学期致辞
2015/07/30 职场文书
导游词之秦始皇兵马俑博物馆
2019/09/29 职场文书