浅谈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 字典dict使用介绍
Nov 30 Python
Python实现的简单文件传输服务器和客户端
Apr 08 Python
浅谈Python 字符串格式化输出(format/printf)
Jul 21 Python
Python采用Django制作简易的知乎日报API
Aug 03 Python
Ubuntu下创建虚拟独立的Python环境全过程
Feb 10 Python
Python系统监控模块psutil功能与经典用法分析
May 24 Python
python实现输入数字的连续加减方法
Jun 22 Python
Django中使用Celery的教程详解
Aug 24 Python
python实现控制COM口的示例
Jul 03 Python
Python中的四种交换数值的方法解析
Nov 18 Python
详解KMP算法以及python如何实现
Sep 18 Python
python开发的自动化运维工具ansible详解
Aug 07 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
通过ICQ网关发送手机短信的PHP源程序
2006/10/09 PHP
对象失去焦点时自己动提交数据的实现代码
2012/11/06 PHP
基于HBase Thrift接口的一些使用问题及相关注意事项的详解
2013/06/03 PHP
HTA版JSMin(省略修饰语若干)基于javascript语言编写
2009/12/24 Javascript
简易js代码实现计算器操作
2013/04/15 Javascript
javascript中获取class的简单实现
2016/07/12 Javascript
如何利用JSHint减少JavaScript的错误
2016/08/23 Javascript
AngularJS入门教程之数据绑定用法示例
2016/11/01 Javascript
利用prop-types第三方库对组件的props中的变量进行类型检测
2017/05/02 Javascript
React为 Vue 引入容器组件和展示组件的教程详解
2018/05/03 Javascript
jQuery解析json格式数据示例
2018/09/01 jQuery
vue引入axios同源跨域问题
2018/09/27 Javascript
Java Varargs 可变参数用法详解
2020/01/28 Javascript
Javascript中的奇葩知识,你知道吗?
2021/01/25 Javascript
javascript实现点击产生随机图形
2021/01/25 Javascript
[03:03]2014DOTA2西雅图国际邀请赛 Alliance战队巡礼
2014/07/07 DOTA
python3.3实现乘法表示例
2014/02/07 Python
Python中使用PyHook监听鼠标和键盘事件实例
2014/07/18 Python
Python解决八皇后问题示例
2018/04/22 Python
tensorflow1.0学习之模型的保存与恢复(Saver)
2018/04/23 Python
python实现最长公共子序列
2018/05/22 Python
Python实现提取XML内容并保存到Excel中的方法
2018/09/01 Python
程序员写Python时的5个坏习惯,你有几条?
2018/11/26 Python
Pandas中DataFrame的分组/分割/合并的实现
2019/07/16 Python
pytorch 预训练层的使用方法
2019/08/20 Python
QML使用Python的函数过程解析
2019/09/26 Python
Python3使用tesserocr识别字母数字验证码的实现
2021/01/29 Python
美国最佳选择产品网站:Best Choice Products
2019/05/27 全球购物
linux面试题参考答案(11)
2012/05/01 面试题
家长会学生演讲稿
2014/04/26 职场文书
服务标兵事迹材料
2014/05/04 职场文书
2014年安全生产责任书
2014/07/22 职场文书
2014领导班子“四风问题”对照检查材料思想汇报(执法局)
2014/09/21 职场文书
机关作风整顿个人剖析材料
2014/10/06 职场文书
党支部四风整改方案
2014/10/25 职场文书
日本动漫十大公认神作:第五现已全网禁播,《死亡笔记》在榜
2022/03/18 日漫