python 装饰器的理解以及类装饰器
python装饰器的作用就是在不改变原有函数结构的情况下给该函数增加一个新功能,就是不入侵到原来函数里面修改代码给其增加一个新功能
先看代码
def out(fn):
def inner(*args, **kwargs):
print("这个是个装饰器,是用来装饰其他函数用的")
ret = fn(*args, **kwargs)
print("******************")
return ret
return inner
上面是个装饰器函数
下面是被装饰的函数
def test(name):
print("这个是fn函数,是被装饰的")
return name
怎么调用呢?
常规方法是这样,把下面的test函数以参数方式传入到上面的装饰器函数,也就是下面这样的方式
foo = out(test)
print(foo("Bob"))
#我们看下执行结果
这个是个装饰器,是用来装饰其他函数用的
这个是fn函数,是被装饰的
******************
Bob #在没有改变test函数代码情况下给test函数增加了新功能
但是以上的调用方式太过于麻烦,有没有简单点的,答案是有的,就是用以下方式调用
@out
def test(name):
print("这个是fn函数,是被装饰的")
return name
##上面的@out方式在python中是叫做语法糖的方式,其实就等价于以下的调用方式
#####
test = out(test) ##==>把out(test)的返回值再赋值给test,想想out(test)的返回值是什么?对了,是inner函数,所以此时test 也就是inner函数了
####
print(test("Bob")) ###==>同理,这里打印出来是是inner函数的返回值,以及inner函数的print函数所打印出的东西,由于Inner函数同时也返回了test函数的返回值,所以就达到了,在不改变test函数情况下,给test函数增加了新功能
我们来看个完整的代码块,以及执行结果
def out(fn):
def inner(*args, **kwargs):
print("这个是个装饰器,是用来装饰其他函数用的")
ret = fn(*args, **kwargs)
print("******************")
return ret
return inner @out
def test(name):
print("这个是fn函数,是被装饰的")
return name
@out
def test_other(name):
print("这是另外一个被装饰的函数")
return name print(test("Bob"))
print("********我是华丽的分割线******")
print(test_other("Joke")) ########执行结果如下########### 这个是个装饰器,是用来装饰其他函数用的
这个是fn函数,是被装饰的
******************
Bob
********我是华丽的分割线******
这个是个装饰器,是用来装饰其他函数用的
这是另外一个被装饰的函数
******************
Joke
看到了吧,两个函数都被正确的装饰了
接下来我们看点有趣的东西,这是我忽然想到的
先看代码块
def out(args):
def inner(fn):
print("这个是个装饰器,是用来装饰其他函数用的")
ret = fn(args)
print("******************")
return ret
return inner def test(name):
print("这个是fn函数,是被装饰的")
return name foo = out("Joke")
print(foo(test)) #####看下执行结果#####
这个是个装饰器,是用来装饰其他函数用的
这个是fn函数,是被装饰的
******************
Joke
是不是很神奇啊,out函数接收常规参数,inner函数接收函数参数也就是func参数
首先 foo = out("Joke"),先传入一个常规str值
然后 print(foo(test)) 打印出foo的返回值,这里的逻辑很重要我们来捋下==>>
foo = out("Joke")等价于把out("Joke")返回值赋给foo,那么这时候foo就等价于inner函数,只是这个args函数给传进去,但是还没使用,你给函数传参是一回事,你用与不用又是另一回事,对不对?所以这里没什么可纠结的吧,然后我们print(foo(test))就等价于把test函数以参数方式传入到inner函数里面,由于你已经传入到一个args了,所以了test函数是可以拿到这个参数的,不明白的建议看下函数的作用域这块,ret = fn(args) 就等价于test(name)明白了吧,最后return ret就得到了test(name),这和上面的装饰器实现方式其实是一致的,只是参数位置调换了而已,装饰器的out的参数是函数,inner参数是常规str参数,这个正好对换位置了,传参方式也相应改变了,我不知道这个有什么用,但是只是想试试,那么我们还能用@out方式来装饰吗,试试就知道了
def out(args):
def inner(fn):
print("这个是个装饰器,是用来装饰其他函数用的")
ret = fn(args)
print("******************")
return ret
return inner @out
def test(name):
print("这个是fn函数,是被装饰的")
return name
print(test("Bob")) ###来看下结果###
这个是个装饰器,是用来装饰其他函数用的
Traceback (most recent call last):
File "E:/python_learn/装饰器.py", line 13, in <module>
print(test("Bob"))
File "E:/python_learn/装饰器.py", line 4, in inner
ret = fn(args)
TypeError: 'str' object is not callable
最后一句告诉你str是不能被调用的,看来更换参数位置后,装饰器也不能这样调用了,这样有助于大家更快理解装饰器。
python 装饰器的理解以及类装饰器的更多相关文章
- python 描述符 上下文管理协议 类装饰器 property metaclass
1.描述符 #!/usr/bin/python env # coding=utf-8 # 数据描述符__get__ __set__ __delete__ ''' 描述符总结 描述符是可以实现大部分py ...
- Java类载入器(二)——自己定义类载入器
用户定制自己的ClassLoader能够实现以下的一些应用: 自己定义路径下查找自己定义的class类文件,或许我们须要的class文件并不总是在已经设置好的Classpath以下,那么我们必须想 ...
- python高级 之(二) --- 类装饰器
装饰器-初级 在不改变原有函数逻辑功能的基础上,为函数添加新的逻辑功能.使代码可读性更高.结构更加清晰.冗余度更低 简介 """ 闭包: 函数嵌套的格式就是闭包.写装饰器 ...
- python装饰器2:类装饰器
装饰器1:函数装饰器 装饰器2:类装饰器 装饰器3:进阶 本文是装饰器相关内容的第二篇,关于类装饰器. "类装饰器"有两种解读方式:用来装饰类的装饰器:类作为装饰器装饰其它东西.你 ...
- 黑马程序猿——Java中的类载入器
------- android培训.java培训.期待与您交流! -------- 类载入器 Java虚拟机中能够安装多个类载入器,系统默认三个主要类载入器,每一个类负责载入特定位置的类: BootS ...
- Jboss7类载入器
1. 类载入器理论知识介绍 类载入器基于Jboss Module,代替了层次类载入环境,避免了当类存在多个版本号时,导致类载入错误. 类载入是基于模块的.必须显示的定义模块依赖.部署也是模块化的,假设 ...
- java类载入器——ClassLoader
Java的设计初衷是主要面向嵌入式领域,对于自己定义的一些类,考虑使用依需求载入原则.即在程序使用到时才载入类,节省内存消耗,这时就可以通过类载入器来动态载入. 假设你平时仅仅是做web开发,那应该非 ...
- 转发对python装饰器的理解
[Python] 对 Python 装饰器的理解的一些心得分享出来给大家参考 原文 http://blog.csdn.net/sxw3718401/article/details/3951958 ...
- python中对变量的作用域LEGB、闭包、装饰器基本理解
一.作用域 在Python程序中创建.改变.查找变量名时,都是在一个保存变量名的空间中进行,我们称之为命名空间,也被称之为作用域.python的作用域是静态的,在源代码中变量名被赋值的位置决定了该变量 ...
随机推荐
- datatables 行与列的数据获取
datatables官网: https://datatables.net/reference/api/cells() 获取数据的方式如下 var table = $(selector).DataTab ...
- windows 安装mysql 5.7的正确姿势
1.首先上MySql的官网下载 https://dev.mysql.com/downloads/mysql/ 2. 以我所选版本为例(免安装版),选择MYSQL Community Server 然 ...
- 1159 Palindrome
Palindrome Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 68562 Accepted: 23869 Desc ...
- React Native backgroundColor 的颜色值
React Native 的 css 跟 web开发中css还是很相似的,其中 backgroundColor 支持的颜色值与 css 一致,为方便查找写在这里. 其他样式可以参考 CSS 样式网站 ...
- h5页面 内嵌h5页面遇到的问题
1.input框无法获取焦点输入内容 input { -webkit-user-select: auto; } 2.div里面放img标签有3px的距离 div { font-size: 0; } i ...
- 移动web总结
Meta标签: 1 <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-sc ...
- 20155208徐子涵 《网络对抗》Exp1 PC平台逆向破解
20155208徐子涵 <网络对抗>Exp1 PC平台逆向破解 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数 ...
- 《Linux内核原理与分析》第五周作业
课本:第4章 系统调用的三层机制(上) -用户态.内核态和中断 -用户态:在低的执行级别下,代码能够掌控的范围有所限制,只能访问部分内存. -内核态:在高的执行级别下,代码可以执行特权指令,访问任意的 ...
- 互联网媒体类型 MIME Type
参考:https://zh.wikipedia.org/wiki/%E4%BA%92%E8%81%94%E7%BD%91%E5%AA%92%E4%BD%93%E7%B1%BB%E5%9E%8B 互联网 ...
- xen虚拟化平台虚拟机在线新加一块磁盘无法识别
截图 报错:you need to shutdown and then restart the vm before it can access the new disk 添加好磁盘后按照提示重启虚拟机 ...