浅谈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分析apache访问日志脚本分享
Feb 26 Python
Python多线程结合队列下载百度音乐的方法
Jul 27 Python
Python正则表达式教程之三:贪婪/非贪婪特性
Mar 02 Python
Python生成数字图片代码分享
Oct 31 Python
浅谈Python接口对json串的处理方法
Dec 19 Python
在python中使用requests 模拟浏览器发送请求数据的方法
Dec 26 Python
Python基本语法之运算符功能与用法详解
Oct 22 Python
在python中创建指定大小的多维数组方式
Nov 28 Python
pytorch进行上采样的种类实例
Feb 18 Python
Python函数必须先定义,后调用说明(函数调用函数例外)
Jun 02 Python
python怎么判断素数
Jul 01 Python
Django中session进行权限管理的使用
Jul 09 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
php获取某个目录大小的代码
2008/09/10 PHP
php的一些小问题
2010/07/03 PHP
php页面缓存ob系列函数介绍
2012/10/18 PHP
PHP设计模式之结构模式的深入解析
2013/06/13 PHP
php自动更新版权信息显示的方法
2015/06/19 PHP
如何解决PHP使用mysql_query查询超大结果集超内存问题
2016/03/14 PHP
Laravel的throttle中间件失效问题解决方法
2016/10/09 PHP
PHP判断json格式是否正确的实现代码
2017/09/20 PHP
thinkphp5.1 文件引入路径问题及注意事项
2018/06/13 PHP
PDO::setAttribute讲解
2019/01/29 PHP
Jquery 改变radio/checkbox选中状态,获取选中的值(示例代码)
2013/12/12 Javascript
javascript实现在某个元素上阻止鼠标右键事件的方法和实例
2014/08/12 Javascript
jQuery Mobile页面返回不需要重新get
2016/04/26 Javascript
Bootstrap 组件之按钮(二)
2016/05/11 Javascript
客户端验证用户名和密码的方法详解
2016/06/16 Javascript
js 实现获取name 相同的页面元素并循环遍历的方法
2017/02/14 Javascript
node实现的爬虫功能示例
2018/05/04 Javascript
js校验开始时间和结束时间
2020/05/26 Javascript
[53:50]CHAOS vs Mineski 2019国际邀请赛小组赛 BO2 第一场 8.16
2019/08/18 DOTA
Python中进程和线程的区别详解
2017/10/29 Python
TensorFlow 实战之实现卷积神经网络的实例讲解
2018/02/26 Python
TensorFlow实现卷积神经网络
2018/05/24 Python
python学生管理系统开发
2019/01/30 Python
Python中的random.uniform()函数教程与实例解析
2019/03/02 Python
Python远程视频监控程序的实例代码
2019/05/05 Python
python异常处理和日志处理方式
2019/12/24 Python
计算Python Numpy向量之间的欧氏距离实例
2020/05/22 Python
HTML5在手机端实现视频全屏展示方法
2020/11/23 HTML / CSS
瑞典最好的运动鞋专卖店:Sneakersnstuff
2016/08/29 全球购物
Abbott Lyon官网:女士手表、珠宝及配件
2020/12/26 全球购物
会计岗位职责范本
2014/03/07 职场文书
学习全国两会精神心得体会范文
2014/03/17 职场文书
《春天来了》教学反思
2014/04/07 职场文书
班主任2015新年寄语
2014/12/08 职场文书
2014年党务公开工作总结
2014/12/09 职场文书
体检通知范文
2015/04/21 职场文书