浅谈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实现监控程序执行时间并将其写入日志的方法
Jun 30 Python
Python的socket模块源码中的一些实现要点分析
Jun 06 Python
python判断字符串是否是json格式方法分享
Nov 07 Python
Python异常对代码运行性能的影响实例解析
Feb 08 Python
解决Python requests库编码 socks5代理的问题
May 07 Python
Python读取mat文件,并保存为pickle格式的方法
Oct 23 Python
Python小工具之消耗系统指定大小内存的方法
Dec 03 Python
python基于SMTP协议发送邮件
May 31 Python
Python字符串和正则表达式中的反斜杠('\')问题详解
Sep 03 Python
Keras SGD 随机梯度下降优化器参数设置方式
Jun 19 Python
解决Django响应JsonResponse返回json格式数据报错问题
Aug 09 Python
详解Python3.8+PyQt5+pyqt5-tools+Pycharm配置详细教程
Nov 02 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
yii实现CheckBox复选框在同一行显示的方法
2014/12/03 PHP
php生成zip文件类实例
2015/04/07 PHP
PHP中的Session对象如何使用
2015/09/25 PHP
ThinkPHP框架实现的邮箱激活功能示例
2018/06/15 PHP
PHP预定义超全局数组变量小结
2018/08/20 PHP
PHP strripos函数用法总结
2019/02/11 PHP
JS实现让网页背景图片斜向移动的方法
2015/02/25 Javascript
AngularJs学习第五篇从Controller控制器谈谈$scope作用域
2016/06/08 Javascript
js获取页面引用的css样式表中的属性值方法(推荐)
2016/08/19 Javascript
AngularJS中$http服务常用的应用及参数
2016/08/22 Javascript
js实现显示手机号码效果
2017/03/09 Javascript
JavaScript基础之this详解
2017/06/04 Javascript
详解创建自定义的Angular Schematics
2018/06/06 Javascript
详解如何在微信小程序中愉快地使用sass
2018/07/30 Javascript
vue实现element-ui对话框可拖拽功能
2018/08/17 Javascript
利用Dectorator分模块存储Vuex状态的实现
2019/02/05 Javascript
Vue 进阶之路(三)
2019/04/18 Javascript
微信小程序 如何获取网络状态
2019/07/26 Javascript
Vue插件之滑动验证码用法详解
2020/04/05 Javascript
vue+Element-ui前端实现分页效果
2020/11/15 Javascript
解决vue页面刷新,数据丢失的问题
2020/11/24 Vue.js
Python语言的面相对象编程方式初步学习
2016/03/12 Python
django框架如何集成celery进行开发
2017/05/24 Python
华为校园招聘上机笔试题 扑克牌大小(python)
2020/04/22 Python
py-charm延长试用期限实例
2019/12/22 Python
python实现扫雷游戏
2020/03/03 Python
QT5 Designer 打不开的问题及解决方法
2020/08/20 Python
eBay奥地利站:eBay.at
2019/07/24 全球购物
奖学金自我鉴定范文
2013/10/03 职场文书
学校欢迎标语
2014/06/18 职场文书
网络文明传播志愿者活动方案
2014/08/20 职场文书
市委常委会班子党的群众路线教育实践活动整改方案
2014/10/25 职场文书
毕业论文致谢范文
2015/05/14 职场文书
党员反四风学习心得体会
2016/01/22 职场文书
给原生html中添加水印遮罩层的实现示例
2021/04/02 Javascript
Python中的程序流程控制语句
2022/02/24 Python