浅谈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 相关文章推荐
在树莓派2或树莓派B+上安装Python和OpenCV的教程
Mar 30 Python
微信跳一跳python辅助软件思路及图像识别源码解析
Jan 04 Python
Python 机器学习库 NumPy入门教程
Apr 19 Python
python实现多人聊天室
Mar 31 Python
提升Python程序性能的7个习惯
Apr 14 Python
python实现定时压缩指定文件夹发送邮件
Dec 22 Python
Python爬虫库BeautifulSoup的介绍与简单使用实例
Jan 25 Python
pyqt5中动画的使用详解
Apr 01 Python
python如何代码集体右移
Jul 20 Python
基于OpenCV的网络实时视频流传输的实现
Nov 15 Python
基于Python的图像阈值化分割(迭代法)
Nov 20 Python
Django扫码抽奖平台的配置过程详解
Jan 14 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
java EJB 加密与解密原理的一个例子
2008/01/11 PHP
php 代码优化的42条建议 推荐
2009/09/25 PHP
php提取微信账单的有效信息
2018/10/01 PHP
laravel5.1 ajax post 传值_token示例
2019/10/24 PHP
List the Codec Files on a Computer
2007/06/11 Javascript
jquery ready()的几种实现方法小结
2010/06/18 Javascript
遨游,飞飞,IE,空中网 浏览器无提示关闭方法
2011/07/11 Javascript
一个JavaScript获取元素当前高度的实例
2014/10/29 Javascript
jQuery实现的网页左侧在线客服效果代码
2015/10/23 Javascript
jQuery使用animate实现ul列表项相互飘动效果示例
2016/09/16 Javascript
利用D3.js实现最简单的柱状图示例代码
2016/12/09 Javascript
nodejs socket实现的服务端和客户端功能示例
2017/06/02 NodeJs
微信小程序之页面跳转和参数传递的实现
2017/09/29 Javascript
Angular4的输入属性与输出属性实例详解
2017/11/29 Javascript
JavaScript中Object值合并方法详解
2017/12/22 Javascript
利用nodeJs anywhere搭建本地服务器环境的方法
2018/05/12 NodeJs
vue打包使用Nginx代理解决跨域问题
2018/08/27 Javascript
微信小程序开发之路由切换页面重定向问题
2018/09/18 Javascript
微信小程序页面缩放式侧滑效果的实现代码
2018/11/15 Javascript
小程序使用分包的示例代码
2020/03/23 Javascript
在Python中使用全局日志时需要注意的问题
2015/05/06 Python
python绘制双柱形图代码实例
2017/12/14 Python
python实现飞机大战微信小游戏
2020/03/21 Python
PyQt5 实现给窗口设置背景图片的方法
2019/06/13 Python
将python运行结果保存至本地文件中的示例讲解
2019/07/11 Python
python实现PID算法及测试的例子
2019/08/08 Python
django xadmin 管理器常用显示设置方式
2020/03/11 Python
html5 canvas移动浏览器上实现图片压缩上传
2016/03/11 HTML / CSS
入党积极分子思想汇报范文
2014/01/05 职场文书
干部鉴定材料
2014/05/18 职场文书
幸福中国演讲稿
2014/09/12 职场文书
幼师求职自荐信
2015/03/26 职场文书
2016年中学植树节活动总结
2016/03/16 职场文书
承诺书的内容有哪些,怎么写?
2019/06/21 职场文书
python非标准时间的转换
2021/07/25 Python
Python内置的数据类型及使用方法
2022/04/13 Python