浅谈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 pass 语句使用示例
Mar 11 Python
python中的实例方法、静态方法、类方法、类变量和实例变量浅析
Apr 26 Python
python解决Fedora解压zip时中文乱码的方法
Sep 18 Python
Python 实现随机数详解及实例代码
Apr 15 Python
python交易记录链的实现过程详解
Jul 03 Python
使用python的turtle函数绘制一个滑稽表情
Feb 28 Python
TensorFlow2.X使用图片制作简单的数据集训练模型
Apr 08 Python
python基于socket模拟实现ssh远程执行命令
Dec 05 Python
python 模块导入问题汇总
Feb 01 Python
Django项目在pycharm新建的步骤方法
Mar 02 Python
Python中Schedule模块使用详解 周期任务神器
Apr 19 Python
Django框架中表单的用法
Jun 10 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实现让页面只能被百度gogole蜘蛛访问的方法
2009/12/29 PHP
PHP常用的文件操作函数经典收藏
2013/04/02 PHP
基于PHP制作验证码
2016/10/12 PHP
php实现的表单验证类完整示例
2019/08/13 PHP
JavaScript.Encode手动解码技巧
2010/07/14 Javascript
Vue中使用vee-validate表单验证的方法
2018/05/09 Javascript
深入浅析Vue中的Prop
2018/06/10 Javascript
微信小程序手机号码验证功能的实例代码
2018/08/28 Javascript
详解vue文件中使用echarts.js的两种方式
2018/10/18 Javascript
element-ui 的el-button组件中添加自定义颜色和图标的实现方法
2018/10/26 Javascript
谈谈React中的Render Props模式
2018/12/06 Javascript
vue打包之后生成一个配置文件修改接口的方法
2018/12/09 Javascript
使用vue-router在Vue页面之间传递数据的方法
2019/07/15 Javascript
axios如何取消重复无用的请求详解
2019/12/15 Javascript
python插入排序算法实例分析
2015/07/03 Python
Python判断变量是否为Json格式的字符串示例
2017/05/03 Python
python使用SMTP发送qq或sina邮件
2017/10/21 Python
tensorflow训练中出现nan问题的解决
2018/02/10 Python
pyqt5利用pyqtDesigner实现登录界面
2019/03/28 Python
Python 获取windows桌面路径的5种方法小结
2019/07/15 Python
python装饰器相当于函数的调用方式
2019/12/27 Python
Python之关于类变量的两种赋值区别详解
2020/03/12 Python
python按顺序重命名文件并分类转移到各个文件夹中的实现代码
2020/07/21 Python
Python urllib request模块发送请求实现过程解析
2020/12/10 Python
Python中Qslider控件实操详解
2021/02/20 Python
Java程序员面试题
2016/09/27 面试题
巾帼文明岗申报材料
2014/05/01 职场文书
禁毒宣传标语
2014/06/19 职场文书
捐款活动总结
2014/08/27 职场文书
商场父亲节活动方案
2014/08/27 职场文书
2014普法依法治理工作总结
2014/12/18 职场文书
行政文员岗位职责
2015/02/04 职场文书
SpringAop日志找不到方法的处理
2021/06/21 Java/Android
Python初学者必备的文件读写指南
2021/06/23 Python
vue组件冲突之引用另一个组件出现组件不显示的问题
2022/04/13 Vue.js
MySQL外键约束(Foreign Key)案例详解
2022/06/28 MySQL