本节内容

一、装饰器导引

  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. 10分钟搭建 App 主流框架

    搭建主流框架界面 0.达成效果 我们玩iPhone应用的时候,有没发现大部分的应用都是上图差不多的结构,下面的TabBar控制器可以切换子控制器,上面又有Navigation导航条 我们本文主要是搭建 ...

  2. delphi 7 求无码

    我们知道delphi很多源码,都是没有提供的,比如BDE,一旦有问题,我们也找不到办法解决,那么那些dcu对应的pas是没有公布的呢?笔者做了个统计. 下面是delphi7 的,如果你的程序有用到没有 ...

  3. delphi程序设计改进可读性一法

    Delphi,Lazarus程序设计改进一法 作者:steven QQ:1565498246 Delphi/Lazarus有一个思想就是方法.函数名调用,后边可以不使用括号(),比如调用函数Now,这 ...

  4. 糟糕的@@identity,SCOPE_IDENTITY ,IDENT_CURRENT

    在某数据库里面,某甲用@@identity来获取最近插入的id值,当在多人环境,发生获取到null值的问题. 那么@@identity是否有存在的必要? 感觉像生个孩子,多了个指头. 有的数据库的ge ...

  5. Java界面编程—API

    Java 的 GUI 提供的对象都存在 java.awt 和 java.swing 两个包中. awt :Abstract Window ToolKit(抽象窗口工具包),需要调用本地系统方法实现功能 ...

  6. h5页面适配iPhone X的方法

    一.原生适配iphoneX 原生适配很简单,查看机型图:   只要用 #define KIsiPhoneX ([UIScreen mainScreen].bounds.size.height>8 ...

  7. docker下安装tomcat

    一,查看tomcat镜像 [root@icompany ~]# docker search tomcat INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED ...

  8. PHP字符串函数运用小案例

    $str = 'ZenD_CONTRollER_FronT'; //转换为Zend_Controller_Front //1.全部转换为小写 $str1 = strtolower($str); //2 ...

  9. MySQL Server参数优化 - innodb_file_per_table(独立表空间)

    1 简介    Innodb存储引擎可将所有数据存放于ibdata*的共享表空间,也可将每张表存放于独立的.ibd文件的独立表空间.    共享表空间以及独立表空间都是针对数据的存储方式而言的.    ...

  10. python之数据库内置方法以及pymysql的使用

    一.mysql内置方法 1)视图的概念和用法 .什么是视图 视图就是通过查询得到一张虚拟表,然后保存下来,下次用的直接使用即可 .为什么要用视图 如果要频繁使用一张虚拟表,可以不用重复查询 .如何用视 ...