浅谈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常见文件操作的函数示例代码
Nov 15 Python
深入分析在Python模块顶层运行的代码引起的一个Bug
Jul 04 Python
用Python的Django框架来制作一个RSS阅读器
Jul 22 Python
详解Python中contextlib上下文管理模块的用法
Jun 28 Python
Python实现钉钉发送报警消息的方法
Feb 20 Python
django中间键重定向实例方法
Nov 10 Python
Python绘图实现显示中文
Dec 04 Python
python装饰器使用实例详解
Dec 14 Python
python飞机大战pygame游戏背景设计详解
Dec 17 Python
序列化Python对象的方法
Aug 01 Python
python单元测试框架pytest的使用示例
Oct 07 Python
python之django路由和视图案例教程
Jul 26 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 数组遍历的差异(array_diff 的实现)
2008/03/23 PHP
浅谈JavaScript中面向对象技术的模拟
2006/09/25 Javascript
html页面显示年月日时分秒和星期几的两种方式
2013/08/20 Javascript
jquery插件开发之实现md5插件
2014/03/17 Javascript
laytpl 精致巧妙的JavaScript模板引擎
2014/08/29 Javascript
JS插件overlib用法实例详解
2015/12/26 Javascript
微信小程序 地图定位简单实例
2016/10/14 Javascript
javascript稀疏数组(sparse array)和密集数组用法分析
2016/12/28 Javascript
node.js基于mongodb的搜索分页示例
2017/01/22 Javascript
Bootstrap笔记之缩略图、警告框实例详解
2017/03/09 Javascript
详解ES6中的三种异步解决方案
2018/06/28 Javascript
Vue.js中使用iView日期选择器并设置开始时间结束时间校验功能
2018/08/12 Javascript
layui实现根据table数据判断按钮显示情况的方法
2019/09/26 Javascript
解决vue页面渲染但dom没渲染的操作
2020/07/27 Javascript
Vue中关闭弹窗组件时销毁并隐藏操作
2020/09/01 Javascript
如何利用node转发请求详解
2020/09/17 Javascript
python字典序问题实例
2014/09/26 Python
Python 性能优化技巧总结
2016/11/01 Python
python numpy 一维数组转变为多维数组的实例
2018/07/02 Python
对Python中实现两个数的值交换的集中方法详解
2019/01/11 Python
TensorFlow2.0:张量的合并与分割实例
2020/01/19 Python
Scrapy框架介绍之Puppeteer渲染的使用
2020/06/19 Python
利用python绘制正态分布曲线
2021/01/04 Python
Python使用cn2an实现中文数字与阿拉伯数字的相互转换
2021/03/02 Python
css3实现文字首尾衔接跑马灯的示例代码
2020/10/16 HTML / CSS
预订旅游活动、景点和旅游:GetYourGuide
2019/09/29 全球购物
澳大利亚最早和最古老的巨型游戏专家:Yardgames
2020/02/20 全球购物
NOTINO英国:在线购买美容和香水
2020/02/25 全球购物
linux比较文件内容的命令是什么
2015/09/23 面试题
个人简历自我评价
2014/02/02 职场文书
软件部经理岗位职责范本
2014/02/25 职场文书
《三峡》教学反思
2014/03/01 职场文书
财政专业大学生职业生涯规划书
2014/09/17 职场文书
2014年残联工作总结
2014/11/21 职场文书
慰问信的写作格式及范文!
2019/06/24 职场文书
Java基础-封装和继承
2021/07/02 Java/Android