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的作用域是静态的,在源代码中变量名被赋值的位置决定了该变量 ...
随机推荐
- Python 进程池的同步方法
import time from multiprocessing import Process,Pool def f1(n): time.sleep(1) #print(n) return n*n i ...
- [转] ROS2源码编译和安装
机器人开源操作系统软件ROS在10年后, 终于推出全新架构的ROS2,代号“ardent”.中文意思为“热心的美洲鳖”,看来ROS2要从ROS1的“海龟”变成“土鳖”系列了. 与此同时,ROS2的编译 ...
- Quartz动态修改数据库cronExpression(无须重启服务器即可更改定时时间)
quartz通过动态设置配置文件确实可以实现与数据库的同步,但现实开发上线后我们基本是不会对配置文件等进行变动,因为重启一次服务器所需的成本太多. 这时,就需要我们仅仅修改数据库就能实现动态的更新定时 ...
- Python重新安装pip
1). 下载pip安装工具: curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py 2).执行升级命令: python2.7 get-pip. ...
- jq实时监测输入框内容改变
$(document) .on('input propertychange','#telInput',function (e) { if (e.type === "input" | ...
- crontab 相关
修改编辑器 select-editor 查看服务状态 service cron status (linux下为crond ,ubuntu为cron) 1-59/2 1,10,12 * * * ...
- SpringAOP 注解方式
Spring-service-mvc.xml <context:component-scan base-package="com.restful.controller,com.rest ...
- SQL Server 幻读 的真实案例
数据库中有表[01_SubjectiveScoreInfo],要实现表中的数据只被查出一次,此表数据量较大,有三四百万数据.表结构也确实不是很合理,无法修改表结构,即使是新增一个字段也会有相当大的修改 ...
- python 保存对象文件
之前用 R 语言一直感觉 .Rdata 格式的文件很好用,可以把每次执行的中间文件保存便于下次调用,刚熟悉 Python 还没接触这块知识,所以有时候做项目不太顺手,索性上网搜了下,整理如下: 模型存 ...
- tomcat 端口修改和内存配置
端口号修改参考:https://jingyan.baidu.com/article/adc815139b12def722bf7377.html Tomcat内存溢出(windows) java.lan ...