浅谈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时间模块datetime、time、calendar的使用方法
Jan 13 Python
Python的爬虫包Beautiful Soup中用正则表达式来搜索
Jan 20 Python
Python自定义函数定义,参数,调用代码解析
Dec 27 Python
Python求两个圆的交点坐标或三个圆的交点坐标方法
Nov 07 Python
python 常见字符串与函数的用法详解
Nov 23 Python
python3利用ctypes传入一个字符串类型的列表方法
Feb 12 Python
python抓取需要扫微信登陆页面
Apr 29 Python
python实现中文文本分句的例子
Jul 15 Python
python scrapy重复执行实现代码详解
Dec 28 Python
python json.dumps中文乱码问题解决
Apr 01 Python
Python APScheduler执行使用方法详解
Dec 10 Python
浅析python字符串前加r、f、u、l 的区别
Jan 24 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 Ubb代码编辑器函数代码
2012/07/05 PHP
CodeIgniter配置之SESSION用法实例分析
2016/01/19 PHP
Zend Framework数据库操作技巧总结
2017/02/18 PHP
关于php unset对json_encode的影响详解
2018/11/14 PHP
Laravel5.5 实现后台管理登录的方法(自定义用户表登录)
2019/09/30 PHP
JS无限树状列表实现代码
2011/01/11 Javascript
jQuery中操控hidden、disable等无值属性的方法
2014/01/06 Javascript
BootStrap创建响应式导航条实例代码
2016/05/31 Javascript
jQuery Easyui datagrid行内实现【添加】、【编辑】、【上移】、【下移】
2016/12/19 Javascript
利用js查找数组中指定元素并返回该元素的所有索引示例
2017/03/29 Javascript
详解webpack2+React 实例demo
2017/09/11 Javascript
浅析vue深复制
2018/01/29 Javascript
解决vue路由后界面没有变化,但是链接有的问题
2018/09/01 Javascript
在vue-cli中引入lodash.js并使用详解
2019/11/13 Javascript
用Python中的字典来处理索引统计的方法
2015/05/05 Python
在DigitalOcean的服务器上部署flaskblog应用
2015/12/19 Python
详解python之简单主机批量管理工具
2017/01/27 Python
python try 异常处理(史上最全)
2019/03/07 Python
使用python serial 获取所有的串口名称的实例
2019/07/02 Python
Python SQLAlchemy入门教程(基本用法)
2019/11/11 Python
Django app配置多个数据库代码实例
2019/12/17 Python
Pycharm调试程序技巧小结
2020/08/08 Python
html5新增的属性和废除的属性简要概述
2013/02/20 HTML / CSS
购买中国最好的电子产品:Geekbuying
2018/03/13 全球购物
澳大利亚领先的运动鞋商店:Hype DC
2018/03/31 全球购物
保加利亚运动鞋购物网站:SneakerStudio.bg
2020/12/23 全球购物
机电专业个人自荐信格式模板
2013/09/23 职场文书
学生安全责任书
2014/04/15 职场文书
特教教师先进事迹
2014/05/21 职场文书
质量在我心中演讲稿
2014/09/02 职场文书
离开雷锋的日子观后感
2015/06/09 职场文书
篮球赛闭幕式主持词
2015/07/03 职场文书
初三数学教学反思
2016/02/17 职场文书
Pygame Time时间控制的具体使用详解
2021/11/17 Python
微信小程序APP的生命周期及页面的生命周期
2022/04/19 Javascript
openGauss数据库JDBC环境连接配置的详细过程(Eclipse)
2022/06/01 Java/Android