python3 装饰器应用举例
【引子】
python 中的装饰器是oop(面向对象编程)设计模式、之装饰器模式的一个应用、由于有语法糖衣的缘故、所以写起来也更加方便
【从一个比较经典的应用场景来讲解装饰器】
有过一定编程经历的工程师、应该都遇到过这样的场景。有一些老的API过时了但是在一段时间内它还是可用的,只是平台会把
它标记为不推荐、也就是说这个API在新的版本里应该不会存在了。比如python-2.x 的时候有raw_input这个函数、但是到了
python-3.x的时候就没有了,在过渡时期平台通常会把将要过时的API标记成“过时”。它是怎么做到的呢?我觉得可行的方法
有两个 1): 用工程师的“寿命”为代价通过手工劳动解决问题 2): 用装饰器优雅的解决
【用寿命来解决问题】
1.1 假设你编写了一个非常牛逼的库、里面包含了一个非常牛逼的函数、它可以完成两个数相加。一开始你的代码是这样的
def add_fun(x,y):
"""
实现两个数相加、并返回合
"""
return x+y
1.2 一段非常长的时间后、你的库在社区中大火、大家也都称你为大神;可是你突然发现了一个问题 add_fun 这个函数以“_fun”
结尾真的够pythonic吗? 后来你还是决定把它改成add这样的函数名,可是有太多的程序依赖于你这个库的add_fun函数了,
如果你突然把这个add_fun函数给改了,那些依赖于这个函数的程序由于再也找不到这个函数了,那么它们会报错,这个明显
不是你想看到的;最后你还是决定单独增加一个add方法同时保留add_fun
def add_fun(x,y):
"""
实现两个数相加、并返回合
"""
return x+y def add(x,y):
"""
实现两个数相加、并返回合
"""
return x+y
1.3 你开始为你这一个改动付出代价(网络上一时有无数人都在问你同一个问题),无数的人在问你为什么会有两上功能完全一样的函数?
于是你把这个问题加到了FQA列表、并且还在你的代码中明确的指出了“add_fun已经过时”
def add_fun(x,y):
"""
实现两个数相加、并返回合
""" print("add_fun 函数已经过时")
return x+y def add(x,y):
"""
实现两个数相加、并返回合
"""
return x+y
1.4 问题是解决了,几天过你可能会发现自己掉粉了,多数人对你这种简单粗暴的方法表示了失望。 有来说一下你的改法有什么问题吧、
1): 你给出函数没办法“封闭”,“封闭”是oop编程中的一个术语,指的你定义好的类、函数应该是功能上完备的,不应该再改了,想
一下如果“场效应管”、“二极管”、“pn结” 这种基础元器件动不动就要改一下,这种感觉就像你是在对一个身在100楼的程序猿说,
你好好上你的班、不过我要修一下大楼的地基。回到程序上来你用什么来保存你的改动不会引入新的bug ?
2): 一个函数还好、如果你成千上万个?那么你这成千上万个都没有封闭、而且每一个你都要改一下、你工作量也不是一般的小、人在
重复劳动下容易出错。
【巧用装饰器解决问题】
先定义一个函数它可以用来包装那些过时的函数、代码如下
def deprecated(fun):
"""deprecated函数会返回一个叫inner的函数、inner函数会返回
fun调用的结果,与直接调用fun得到值不同的是inner会先打印一行提示
表明fun已经过时
"""
def inner(x,y):
print("{fun.__name__} 函数已经过时".format(fun=fun))
return fun(x,y)
return inner def add_fun(x,y):
"""
实现两个数相加、并返回合
"""
return x+y add_fun = deprecated(add_fun) #包装add_fun函数 def add(x,y):
"""
实现两个数相加、并返回合
"""
return x+y if __name__=="__main__":
print(add_fun(1,1))
调用时的输出
python3 dc.py add_fun 函数已经过时
从上面的例子我们看出装饰器并没有什么特别这只不过是一个“返回可调用对象的可调用对象”、下面我们讲一下装饰器的“语法糖衣 @写法”
def deprecated(fun):
"""deprecated函数会返回一个叫inner的函数、inner函数会返回
fun调用的结果,与直接调用fun得到值不同的是inner会先打印一行提示
表明fun已经过时
"""
def inner(x,y):
print("{fun.__name__} 函数已经过时".format(fun=fun))
return fun(x,y)
return inner @deprecated # 使用@写法来实现包装
def add_fun(x,y):
"""
实现两个数相加、并返回合
"""
return x+y def add(x,y):
"""
实现两个数相加、并返回合
"""
return x+y if __name__=="__main__":
print(add_fun(1,1))
从上面可以看出在使用装饰器来处理代码的情况下,add_fun是“封闭”的 ,@写法与上面的函数调用方式下包装add_fun是等价的。输出结果如下
python3 dc.py
add_fun 函数已经过时
python3 装饰器应用举例的更多相关文章
- 净心诀---python3装饰器
python3装饰器 装饰器作用 简单理解:可以为已有函数添加额外功能 例: 已有2个函数如下 def MyFunc1(): print("This is a print function1 ...
- python3 装饰器全解
本章结构: 1.理解装饰器的前提准备 2.装饰器:无参/带参的被装饰函数,无参/带参的装饰函数 3.装饰器的缺点 4.python3的内置装饰器 5.本文参考 理解装饰器的前提:1.所有东西都是对象( ...
- python3 装饰器
#Author by Andy#_*_ coding:utf-8 _*_#装饰器的原则及构成:# 原则:# 1.不能修改被装饰函数的源代码.# 2.不能修改被装饰函数的调用方式.# 3.不能改变被装饰 ...
- python3 装饰器初识 NLP第三条
还是先抄一条NLP假设... 三,有效果比有道理更重要 光说做法有道理或者正确而不顾是否有效果,是在自欺欺人. 在三赢(我好,人好,世界好)的原则基础上追求效果,比坚持什么是对的更有意义. 说道理 ...
- python3装饰器用法示例
装饰器在编写后台的逻辑时有可能会用到,比方说一个场景:公司的员工想要登录自己公司的考勤记录系统去修改自己的考勤,以前是随便谁都有权限去修改,这样老板不同意了,现在,要在你登录前加一个权限验证的逻辑,如 ...
- python3装饰器
由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ... print('2015-3-25') ... >> ...
- python3 装饰器修复技术@wraps到底是什么?
Python 装饰器中的@wraps的作用: 装饰器的作用: 在不改变原有功能代码的基础上,添加额外的功能,如用户验证等 @wraps(view_func)的作用: 不改变使 ...
- Python3装饰器的使用
装饰器 简易装饰器模板 def wrapper(func): def inner(*args,**kwargs): print('主代码前添加的功能') ret=func(*args,**kwargs ...
- python3装饰器-进阶
一.wraps 作用:优化装饰器 from functools import wraps # 导入wraps def wrapper(f): @wraps(f) # wraps的语法糖 def inn ...
随机推荐
- mysqld.exe
mysqld.exe是mysql的服务端程序,开启之后才能使用mysql.exe 将mysql安装成服务很简单: mysqld.exe install mysql 删除服务也很简单: sc delet ...
- MapReduce三种路径输入
目前为止知道MapReduce有三种路径输入方式.1.第一种是通过一下方式输入: FileInputFormat.addInputPath(job, new Path(args[0]));FileIn ...
- VB.NET版+三层实现登陆
三层已经学了一些时间了,開始认为自己能够用C#敲代码了,就用C#写了一个实现登陆的,真正再用在机房中.还是认为非常吃力的,所以.决定用vb.net敲了.以下是我用vb.net实现的登陆.能够给大家做一 ...
- Eclipse远程连接HBase
在Eclipse下新建一个Map/Reduce项目,并将以下jar添加到Build path: 程序代码: package thathbase; import java.io.IOException; ...
- node.js模块化写法入门
子模块的写法: function SVN(){ console.log('svn initialized'); return this; } function getInstance() { cons ...
- Java千百问_05面向对象(005)_接口和抽象类有什么差别
点击进入_很多其它_Java千百问 1.接口和抽象类有什么差别 在Java语言中.抽象类abstract class和接口interface是抽象定义的两种机制. 正是因为这两种机制的存在,才赋予了J ...
- JAVA中的CountDownLatch、CyclicBarrier、Semaphore的简单测试
因公司需要做一个对于CountDownLatch的分享,特写了此blog. 具体细节可以参见:小结java自带的跟锁相关的一些类 在做这个分享的过程中发现了Main和junit的运行的区别,在另外一个 ...
- Windows下 VS2015编译levelDB(nmake)
VS2015编译levelDB Leveldb是一个google实现的非常高效的kv数据库,非常适合嵌入到程序中.如果有简单的key-value数据库需求,而又想使用一个数据库服务的话,levelDB ...
- Inno Setup入门(九)——修改安装过程中的文字显示
前面说到过可以使用不用的语言文件实现不同的显示方式,方便与国际接轨,事实上即使没有语言文件也可以实现修改.[Messages] 段用于定义安装程序和卸载程序中显示的消息.一般不需要创建 [Messag ...
- 管理多tomcat实例的shell脚本
为了简化tomcat的部署复杂度, 把以前单独配置的脚本提出来做了一个带参数的, 可以用于单机环境下的多tomcat实例管理. 其中deploy功能, 会将指定的模块war按日期时间更名备份后, 再部 ...