本节内容

一、装饰器导引

  1、函数对象特性

  2、扩展业务功能需求

  3、各种解决方案

二、装饰器解析

  1、装饰器基本概念

  2、无参装饰器解析

 

一、装饰器导引

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自动化开发 - 装饰器的更多相关文章

  1. python自动化之装饰器

    1 高阶函数 满足下列条件之一就可成函数为高阶函数 某一函数当做参数传入另一个函数中 函数的返回值包含n个函数,n>0 高阶函数示范 def bar(): print 'in the bar' ...

  2. Day04 - Python 迭代器、装饰器、软件开发规范

    1. 列表生成式 实现对列表中每个数值都加一 第一种,使用for循环,取列表中的值,值加一后,添加到一空列表中,并将新列表赋值给原列表 >>> a = [0, 1, 2, 3, 4, ...

  3. python高级之装饰器

    python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函数的定义: 满足下面两个条件之 ...

  4. 第二篇:python高级之装饰器

    python高级之装饰器   python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函 ...

  5. python设计模式之装饰器详解(三)

    python的装饰器使用是python语言一个非常重要的部分,装饰器是程序设计模式中装饰模式的具体化,python提供了特殊的语法糖可以非常方便的实现装饰模式. 系列文章 python设计模式之单例模 ...

  6. python中的装饰器decorator

    python中的装饰器 装饰器是为了解决以下描述的问题而产生的方法 我们在已有的函数代码的基础上,想要动态的为这个函数增加功能而又不改变原函数的代码 例如有三个函数: def f1(x): retur ...

  7. Python入门篇-装饰器

    Python入门篇-装饰器 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.装饰器概述 装饰器(无参) 它是一个函数 函数作为它的形参 返回值也是一个函数 可以使用@functi ...

  8. 面向切面编程AOP——加锁、cache、logging、trace、同步等这些较通用的操作,如果都写一个类,则每个用到这些功能的类使用多继承非常难看,AOP就是解决这个问题的,python AOP就是装饰器

    面向切面编程(AOP)是一种编程思想,与OOP并不矛盾,只是它们的关注点相同.面向对象的目的在于抽象和管理,而面向切面的目的在于解耦和复用. 举两个大家都接触过的AOP的例子: 1)java中myba ...

  9. 三分钟搞定Python中的装饰器

    python的装饰器是python的特色高级功能之一,言简意赅得说,其作用是在不改变其原有函数和类的定义的基础上,给他们增添新的功能. 装饰器存在的意义是什么呢?我们知道,在python中函数可以调用 ...

随机推荐

  1. nodejs 数字字节转换操作

    function number2Bytes(i) { var arr = new Int32Array(1); arr[0] = 0; var buf = Buffer.from(arr.buffer ...

  2. HDU 3861.The King’s Problem 强联通分量+最小路径覆盖

    The King’s Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  3. boost asio 一个聊天的基本框架

    示例代码 #include "Util.h" #include "MyAsio.h" #include "TcpConnectionManager.h ...

  4. .Net直接将Web页面table导出到Excel

    项目管理系统有个统计表需要导出到Excel表中.常用的方法是在后台C#代码查询数据再写入Excel表中最后保存在目标路径. 为减轻数据库服务器的压力和保持页面的样式,能否直接将页面的表格直接导出到Ex ...

  5. Spring 常见注解

    @Component:标准一个普通的spring Bean类. @Controller:标注一个控制器组件类. @Service:标注一个业务逻辑组件类. @Repository:标注一个DAO组件类 ...

  6. 内存溢出和内存泄漏的区别(ZZ)

      内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory:比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出 ...

  7. Python内置logging模块

    最近调试Python代码比较多,发现logging模块很好用. 我的用法如下: import logging logging.basicConfig(level=logging.INFO, forma ...

  8. Find the location of libmysqlclient.so.X file in Linux environments

    I'm putting together a script that has a requirement of knowing libmysqlclient.so.[15|16|18] .so fil ...

  9. windows下如何修改mysql的端口号

  10. android 自动更新

    http://blog.csdn.net/zml_2015/article/details/50756703