浅谈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是编译运行的验证方法
Jan 30 Python
Django Highcharts制作图表
Aug 27 Python
Python中表示字符串的三种方法
Sep 06 Python
Python数据结构与算法之二叉树结构定义与遍历方法详解
Dec 12 Python
Windows下的Python 3.6.1的下载与安装图文详解(适合32位和64位)
Feb 21 Python
tensorflow: 查看 tensor详细数值方法
Jun 13 Python
Python爬取数据并写入MySQL数据库的实例
Jun 21 Python
python Pandas如何对数据集随机抽样
Jul 29 Python
Python 使用type来定义类的实现
Nov 19 Python
Tensorflow实现在训练好的模型上进行测试
Jan 20 Python
教你使用Sublime text3搭建Python开发环境及常用插件安装另分享Sublime text3最新激活注册码
Nov 12 Python
python实现定时发送邮件到指定邮箱
Dec 23 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网站备份程序代码分享
2011/06/10 PHP
php读取mysql乱码,用set names XXX解决的原理分享
2011/12/29 PHP
PHP获取本周第一天和最后一天示例代码
2014/02/24 PHP
php实现上传图片生成缩略图示例
2014/04/13 PHP
yii2.0整合阿里云oss上传单个文件的示例
2017/09/19 PHP
解决在Laravel 中处理OPTIONS请求的问题
2019/10/11 PHP
php面向对象基础详解【星际争霸游戏案例】
2020/01/23 PHP
使用git迁移Laravel项目至新开发环境的步骤详解
2020/04/06 PHP
PHP随机生成中文段落示例【测试网站内容时使用】
2020/04/26 PHP
Aster vs KG BO3 第三场2.19
2021/03/10 DOTA
javascript showModalDialog 内跳转页面的问题
2010/11/25 Javascript
JS正则验证邮箱的格式详细介绍
2013/11/19 Javascript
js操作输入框中选择内容兼容IE及其他主流浏览器
2014/04/22 Javascript
javascript去除字符串中所有标点符号和提取纯文本的正则
2014/06/07 Javascript
与Math.pow 相反的函数使用介绍
2014/08/04 Javascript
jscript读写二进制文件的方法
2015/04/22 Javascript
分享jQuery插件的学习笔记
2016/01/14 Javascript
JS操作时间 - UNIX时间戳的简单介绍(必看篇)
2017/08/16 Javascript
如何从零开始手写Koa2框架
2019/03/22 Javascript
JavaScript实现轮播图片完整代码
2020/03/07 Javascript
vue 组件间的通信之子组件向父组件传值的方式
2020/07/29 Javascript
JavaScript canvas实现文字时钟
2021/01/10 Javascript
Python之web模板应用
2017/12/26 Python
python生成九宫格图片
2018/11/19 Python
Python建造者模式案例运行原理解析
2020/06/29 Python
利用html5 canvas动态画饼状图的示例代码
2018/04/02 HTML / CSS
关于环保的标语
2014/06/13 职场文书
关于环保的活动方案
2014/08/25 职场文书
付款委托书范本
2014/10/05 职场文书
2015年全民国防教育日活动总结
2015/03/23 职场文书
导游词之无锡丝业博物馆
2019/11/12 职场文书
解决Nginx 配置 proxy_pass 后 返回404问题
2021/03/31 Servers
Python 类,对象,数据分类,函数参数传递详解
2021/09/25 Python
一篇文章告诉你如何实现Vue前端分页和后端分页
2022/02/18 Vue.js
MySQL数据库如何给表设置约束详解
2022/03/13 MySQL
Win11更新失败并提示0xc1900101
2022/04/19 数码科技