Python自动化开发 - 装饰器
本节内容
| 一、装饰器导引 |
1、函数对象特性
#### 第一波 ####
def foo(): # 表示定义函数
print('foo') # 表示函数体 foo #表示是函数名,指向函数体的地址
foo() #表示执行foo函数 #### 第二波 ####
def foo():
print('foo') foo = lambda x: x + 1 foo() # 执行下面的lambda表达式,而不再是原来的foo函数,因为函数 foo 被重新定义了 #### 第三波 ####
def now():
print('2017-01-12') f = now
f() # 执行结果 2017-02-12 # 函数也是一个对象,而且函数对象也可以被赋值给变量,所以通过该变量也能调用该函数
2、扩展业功能需求
初创公司有N个业务部门,1个基础平台部门,基础平台负责提供底层的功能,如:数据库操作、redis调用、监控API等功能。
业务部门使用基础功能时,只需调用基础平台提供的功能即可。如下:
############### 基础平台提供的功能如下 ############### def f1():
print('f1') def f2():
print('f2') def f3():
print('f3') def f4():
print('f4') ############### 业务部门A 调用基础平台提供的功能 ############### f1()
f2()
f3()
f4() ############### 业务部门B 调用基础平台提供的功能 ############### f1()
f2()
f3()
f4()
目前公司有条不紊的进行着,但是,以前基础平台的开发人员在写代码时候没有关注验证相关的问题,即:基础平台的提供的功能可以被任何人使用。
现在需要对基础平台的所有功能进行重构,为平台提供的所有功能添加验证机制,即:执行功能前,先进行验证。
3、各种解决方案
员工一,他是这么做的:
跟每个业务部门交涉,每个业务部门自己写代码,调用基础平台的功能之前先验证。诶,这样一来基础平台就不需要做任何修改了。
当天他被开除了。
员工二,他是这么做的:
只对基础平台的代码进行重构,让N业务部门无需做任何修改
############### 基础平台提供的功能如下 ############### def f1():
# 验证1
# 验证2
# 验证3
print('f1') def f2():
# 验证1
# 验证2
# 验证3
print('f2') def f3():
# 验证1
# 验证2
# 验证3
print ('f3') def f4():
# 验证1
# 验证2
# 验证3
print ('f4') ############### 业务部门不变 ###############
### 业务部门A 调用基础平台提供的功能### f1()
f2()
f3()
f4() ### 业务部门B 调用基础平台提供的功能 ### f1()
f2()
f3()
f4()
过了一周,他被开除了
员工三,他是这么做的:
只对基础平台的代码进行重构,其他业务部门无需做任何修改
############### 基础平台提供的功能如下 ############### def check_login():
# 验证1
# 验证2
# 验证3
pass def f1(): check_login() print('f1') def f2(): check_login() print('f2') def f3(): check_login() print('f3') def f4(): check_login() print('f4')
战战兢兢,员工三保留了工作,进一步观察,哎工作不易啊
最终大BOSS给了解答:
写代码要遵循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,
但可以被扩展,即:
- 封闭:已实现的功能代码块,不能被修改
- 开放:扩展已实现的代码功能块
如果将开放封闭原则应用到上述需求中,那么就不允许在函数f1、f2、f3、f4的内部进行修改代码,大BOSS给了如下一个实现方案
def w1(func):
def inner():
# 验证1
# 验证2
# 验证3
return func()
return inner @w1
def f1():
print('f1')
@w1
def f2():
print('f2')
@w1
def f3():
print('f3')
@w1
def f4():
print('f4)
对于上述代码,也是仅仅对基础平台的代码进行修改,就可以实现在其他人调用函数f1、f2、f3、f4之前都进行【验证】,
并且其他业务部门无需做任何的操作。内部的实现原理就是装饰器
| 二、装饰器解析 |
1、装饰器基本概念
A 装饰器定义:本质是函数,功能是为其他函数添加新功能
B 遵循原则:
不修改被修饰函数的源代码
为被装饰函数添加新功能后,不修改被修饰函数的调用方式
C 分解装饰器:装饰器 = 高阶函数 + 函数嵌套 + 闭包
其中一个函数参数为函数名,或者函数的返回值是一个函数名,这样的函数称之为高阶函数
2、无参装饰器解析
单独以f1为例:
# 定义装饰器
def w1(func):
def inner():
# 验证功能
print('我是为函数 %s 添加的验证模块' % func.__name__)
return func()
return inner # @w1为Python的语法糖,下面一段代码本质执行f1 = w1(f1)
@w1
def f1(): # 不修改被修饰函数的源代码
print('调用f1功能') f1() # 不修改被修饰函数的调用方式
程序从上到下依次执行
(一) def w1(func): # 将函数w1加载到内存,未执行w1函数体
(二) @w1 # @函数名,Python一种语法糖,等价于 f1 = w1(f1),其中参数f1被保存下来。所以@w1内部执行如下
执行w1()函数体,参数为f1:
def inner(): # 将函数inner加载到内存,未执行inner函数体
return inner
以上操作完成 函数f1 = w1(f1),无论原先函数f1,还是被重构inner()重构的函数f1,皆未被执行
(三) f1() # 执行函数被重构的f1()函数体,也就是执行函数 inner():
print('我是为函数 %s 添加的验证模块' % func.__name__)
return func():调用原函数 f1(),也就是 print('调用f1功能')
3、有参装饰器解析
Python自动化开发 - 装饰器的更多相关文章
- python自动化之装饰器
1 高阶函数 满足下列条件之一就可成函数为高阶函数 某一函数当做参数传入另一个函数中 函数的返回值包含n个函数,n>0 高阶函数示范 def bar(): print 'in the bar' ...
- Day04 - Python 迭代器、装饰器、软件开发规范
1. 列表生成式 实现对列表中每个数值都加一 第一种,使用for循环,取列表中的值,值加一后,添加到一空列表中,并将新列表赋值给原列表 >>> a = [0, 1, 2, 3, 4, ...
- python高级之装饰器
python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函数的定义: 满足下面两个条件之 ...
- 第二篇:python高级之装饰器
python高级之装饰器 python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函 ...
- python设计模式之装饰器详解(三)
python的装饰器使用是python语言一个非常重要的部分,装饰器是程序设计模式中装饰模式的具体化,python提供了特殊的语法糖可以非常方便的实现装饰模式. 系列文章 python设计模式之单例模 ...
- python中的装饰器decorator
python中的装饰器 装饰器是为了解决以下描述的问题而产生的方法 我们在已有的函数代码的基础上,想要动态的为这个函数增加功能而又不改变原函数的代码 例如有三个函数: def f1(x): retur ...
- Python入门篇-装饰器
Python入门篇-装饰器 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.装饰器概述 装饰器(无参) 它是一个函数 函数作为它的形参 返回值也是一个函数 可以使用@functi ...
- 面向切面编程AOP——加锁、cache、logging、trace、同步等这些较通用的操作,如果都写一个类,则每个用到这些功能的类使用多继承非常难看,AOP就是解决这个问题的,python AOP就是装饰器
面向切面编程(AOP)是一种编程思想,与OOP并不矛盾,只是它们的关注点相同.面向对象的目的在于抽象和管理,而面向切面的目的在于解耦和复用. 举两个大家都接触过的AOP的例子: 1)java中myba ...
- 三分钟搞定Python中的装饰器
python的装饰器是python的特色高级功能之一,言简意赅得说,其作用是在不改变其原有函数和类的定义的基础上,给他们增添新的功能. 装饰器存在的意义是什么呢?我们知道,在python中函数可以调用 ...
随机推荐
- GM Tech 2 works with Hummer Yes or No
This is about GM Tech 2 scan tool for Hummer troubleshooting and programming. Can I have a cheap Tec ...
- usr/include/c++/6.4.1/bits/stl_relops.:67: Parse error at "std"
问题描述: 1.编译某qt工程的32位架构二进制包时,出现了上面错误,具体错误信息如下 qmake-qt5 -o ProductLicense/Makefile ProductLicense/Prod ...
- jsonp,ajax,json问题
JSONP技术 JSONP是解决跨域问题的一种常见方式 跨域问题,因为浏览器有同源策略,所以当不同域间进行数据交互的时候就会出现跨域问题 同源策略:只有在同协议.同域名.同端口的情况下才能进去数据交互 ...
- UI设计师经常去的五个网站
1.站酷 站酷(ZCOOL),中国人气设计师互动平台.深耕设计领域十年,站酷聚集了470万优秀设计师.摄影师.插画师.艺术家.创意人,设计创意群体中具有较高的影响力与号召力. 2.花瓣 花瓣网, ...
- [SoapUI] Groovy获取HTTP Status
def value = messageExchange.responseHeaders["#status#"] def httpResponseHeaders = context. ...
- Spring Environment(三)生命周期
Spring Environment(三)生命周期 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Spring Envi ...
- vc项目中加载多个lib遇到的问题
一个VC项目中 在网络加密 json解析等方面 加载了多个第三方库和文件 boost cryptpp rapidjson mysql的连接池等等 在使用mysql++的时候 多次报错 LNK 20 ...
- Android Studio Tip of the Day
1. Alt + Q 可以查看一个方法的简单参数列表. 2. 查看一个类,如果是eclipse的话,一般直接是F3, 现在的F3好痛苦.只能改为Ctrl + H,将就着用. 3. Ctrl + J 语 ...
- sql条件查询-日期比较(取年月部分)
查询当年当月的数据: select * from compalete_task where to_Char(create_date,'yyyyMM') = to_Char(sysdate,'yyyyM ...
- 消息中间件及WebSphere MQ入门(转载)
消息队列技术是分布式应用间交换信息的一种技术.消息队列可驻留在内存或磁盘上,队列存储消息直到它们被应用程序读走.通过消息队列,应用程序可独立地执行--它们不需要知道彼此的位置.或在继续执行前不需要等待 ...