本节内容

一、装饰器导引

  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. the example of dlsym

    void *handle; int i, (*fptr)(int); /* open the needed object */ handle = dlopen("/usr/home/me/l ...

  2. 超全面!UI设计师如何适配2018新款iPhone

    北京时间9月13日凌晨1点,苹果在美国加利福尼亚州的Apple Park园区召开了2018年苹果秋季新品发布会. 很多人对这次科技界的春晚充满了期待,除了那些让人“剁手”的新品,设计师关注的还有新手机 ...

  3. MySQL表的相关操作

    操作数据表之前,必须先选择相应数据表所在的数据库 mysql> USE databaseName; -- 选择数据库 查看该数据库下的数据表 mysql> show tables; 确定数 ...

  4. Ubuntu 双网卡设置

    闲话不多说,直接正题 因为chinanet信号不强,所以买了个usb无线网卡,平常又要做开发,要连着开发板,不知怎么回事,一旦自带无线网卡连上内网的无线路由,就不能访问外网了. 网上搜了好久,终于查到 ...

  5. easyui 获取特定页签tab

    var findTab=$('#mytabs').tabs('getTab','财务信息').panel('options').tab; var findTabIndex = $('#tab').ta ...

  6. 解析vue2.0中render:h=>h(App)的具体意思

    render:h=>h(App)是ES6中的箭头函数写法,等价于render:function(h){return h(App);}. 注意点:1.箭头函数中的this是 指向 包裹this所在 ...

  7. 1.about

    1)about Evarobot a.Evarobot Tech Specs 2)应用场景 Using a PC running visualisation/monitoring software a ...

  8. 如何烧写BIOS到SD卡里面

    针对TINY6410 ADK型号 1.SD卡格式化为FAT32或者FAT格式 2.将SD卡插入USB接口的读卡器,并插在PC的USB口 3.“以管理员身份运行”SD-Flasher.exe(在tiny ...

  9. Android Camera后台拍照

    http://item.congci.com/item/android-camera-houtai-paizhao 有许多人希望在不让用户知道的情况下,使用Android后台Service调用摄像头拍 ...

  10. 728. Self Dividing Numbers

    class Solution { public: vector<int> selfDividingNumbers(int left, int right) { vector<int& ...