浅谈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 相关文章推荐
go和python调用其它程序并得到程序输出
Feb 10 Python
python实现simhash算法实例
Apr 25 Python
Python实现简单的获取图片爬虫功能示例
Jul 12 Python
疯狂上涨的Python 开发者应从2.x还是3.x着手?
Nov 16 Python
磁盘垃圾文件清理器python代码实现
Aug 24 Python
Python图像处理之简单画板实现方法示例
Aug 30 Python
python实现微信小程序自动回复
Sep 10 Python
python 执行文件时额外参数获取的实例
Dec 18 Python
python super的使用方法及实例详解
Sep 25 Python
python使用html2text库实现从HTML转markdown的方法详解
Feb 21 Python
解决pycharm安装第三方库失败的问题
May 09 Python
Python numpy大矩阵运算内存不足如何解决
Nov 19 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输入流php://input介绍
2012/09/18 PHP
PHP FTP操作类代码( 上传、拷贝、移动、删除文件/创建目录)
2014/05/10 PHP
php把时间戳转换成多少时间之前函数的实例
2016/11/16 PHP
laravel中短信发送验证码的实现方法
2018/04/25 PHP
PHP yield关键字功能与用法分析
2019/01/03 PHP
PHP 实现重载
2021/03/09 PHP
document.getElementById方法在Firefox与IE中的区别
2010/05/18 Javascript
JavaScript的parseInt 取整使用
2011/05/09 Javascript
js判读浏览器是否支持html5的canvas的代码
2013/11/18 Javascript
js动态拼接正则表达式的两种方法
2014/03/04 Javascript
基于javascript制作微信聊天面板
2020/08/09 Javascript
Angular中使用ui router实现系统权限控制及开发遇到问题
2016/09/23 Javascript
jQuery实现移动端手机商城购物车功能
2016/09/24 Javascript
jquery编写日期选择器
2017/03/16 Javascript
JS实现数组按升序及降序排列的方法
2017/04/26 Javascript
Easyui使用Dialog行内按钮布局的实例
2017/07/27 Javascript
webpack3+React 的配置全解
2017/08/21 Javascript
JS实现简易换图时钟功能分析
2018/01/04 Javascript
JavaScript 实现同时选取多个时间段的方法
2019/10/17 Javascript
[01:50]2014DOTA2西雅图邀请赛 专访欢乐周宝龙
2014/07/08 DOTA
用python + openpyxl处理excel2007文档思路以及心得
2014/07/14 Python
python实现上传下载文件功能
2020/11/19 Python
Python List cmp()知识点总结
2019/02/18 Python
Python实现微信消息防撤回功能的实例代码
2019/04/29 Python
推荐8款常用的Python GUI图形界面开发框架
2020/02/23 Python
python实现随机加减法生成器
2020/02/24 Python
Python 定义只读属性的实现方式
2020/03/05 Python
解决pyecharts运行后产生的html文件用浏览器打开空白
2020/03/11 Python
HTML5使用Audio标签实现歌词同步的效果
2016/03/17 HTML / CSS
Agoda.com官方网站:便宜预订全球酒店,高达80%的折扣
2018/04/04 全球购物
库存图片、照片、矢量图、视频和音乐:Shutterstock
2021/02/12 全球购物
银行实习人员自我鉴定
2013/09/22 职场文书
信息管理专业推荐信
2013/10/29 职场文书
会计专业毕业生自荐信范文
2013/12/20 职场文书
财务支持类个人的自我评价
2014/02/14 职场文书
教师党员先进性教育自我剖析材料思想汇报
2014/09/24 职场文书