自述:公司部分web项目是用Python写的,分配给我处理bug问题,于是有缘深入接触该技术,多余不说,对于数据分析Python确实比java方便很多,你可以随意编写一段代码将复杂报表快速处理,相对shell更容易编写理解。

本文主要梳理了Python decorator的实现思路,解释了为什么Python decorator是现在这个样子。

关于代理模式、装饰模式

设计模式中经常提到的代理模式、装饰模式,这两种叫法实际上是说的同一件事,只是侧重点有所不同而已。

这两者都是通过在原有对象的基础上封装一层对象,通过调用封装后的对象而不是原来的对象来实现代理/装饰的目的。

例如:(以Java为例)

publicclassCountProxyimplementsCount{

private CountImpl countImpl;

public CountProxy(CountImplcountImpl){

this.countImpl = countImpl;

}

@Override

public void queryCount(){

System.out.println("事务处理之前");

//调用委托类的方法;

countImpl.queryCount();

System.out.println("事务处理之后");

}

@Override

public void updateCount(){

System.out.println("事务处理之前");

//调用委托类的方法;

countImpl.updateCount();

System.out.println("事务处理之后");

}

}

在这个例子中CountProxy是对CountImpl的封装。

使用者通过CountProxy.queryCount方法来调用CountImpl.queryCount方法,这被称为代理,即CountProxy是代理类,CountImpl是被代理类。

在CountProxy.queryCount方法中,可以在CountImpl.queryCount方法调用之前和之后添加一些额外的操作,被称为装饰,即CountProxy是装饰类,CountImpl是被装饰类。

如果强调通过CountProxy 对CountImpl进行代理的作用,则称为代理模式;

如果强调通过CountProxy 对CountImpl增加额外的操作,则称为装饰模式;

不论是哪种称呼,其本质都在于对原有对象的封装。其封装的目的在于增强所封装对象的功能或管理所封装的对象。

从上面的例子也可以发现,代理/封装所围绕的核心是可调用对象(比如函数)。

Python中的代理/装饰

Python中的可调用对象包括函数、方法、实现了__call__方法的类。Python中的函数也是对象,可以作为高阶函数的参数传入或返回值返回。因此,当代理/装饰的对象是函数时,可以使用高阶函数来对某个函数进行封装。

例如:

def query_count_proxy(fun,name,age):

print('do something before')

rv = fun(name,age)

print('do something after')

returnrv

def query_count(name,age):

print('name is %s, age is %d' %(name,age))

query_count_proxy(query_count,'Lee',20)

但是,这个例子中,query_count函数作为参数传入query_count_proxy函数中,并在query_count_proxy函数中被调用,其结果作为返回值返回。这就完成了代理的功能,同时,在调用query_count函数的前后,我们还增加了装饰代码。但是,query_count_proxy的函数参数与query_count不一样了,理想的代理应该保持接口一致才对。

为了保持一致,我们可以利用高阶函数可以返回函数的特点来完成:

def query_count_proxy(fun):

def wrapper(name,age):

print('do something before')

rv = fun(name,age)

print('do something after')

returnrv

returnwrapper

def query_count(name,age):

print('name is %s, age is %d' %(name,age))

query_count_proxy(query_count)('Lee',20)

修改后的例子,query_count_proxy仅负责接受被代理的函数query_count作为参数,同时,返回一个函数对象wrapper作为返回值,真正的封装动作在wrapper这个函数中完成。

此时,如果调用query_count_proxy(query_count)就得到了wrapper函数对象,则,执行query_count_proxy(query_count)('Lee', 20)就相当于执行了wrapper('Lee', 20)。

但是可以看到,query_count_proxy(query_count)('Lee', 20)这种使用方法,仍然不能保证一致。

为了保持一致,我们需要利用Python中对象与其名称可以动态绑定的特点。不使用query_count_proxy(quer_count)('Lee', 20)来调用代理函数,而是使用下面两句:

query_count = query_count_proxy(query_count)

query_count('Lee',20)

执行query_count_proxy(query_count)生成wrapper函数对象,将这个对象通过query_count = query_count_proxy(query_count)绑定到query_count这个名字上来,这样执行query_count('Lee', 20)时,其实执行的是wrapper('Lee', 20)。

这么做的结果就是:使用代理时调用query_count('Lee', 20)与不使用代理时调用query_count('Lee', 20)对使用者而言保持不变,不用改变代码,但是在真正执行时,使用的是代理/装饰后的函数。

这里,基本利用Python的高阶函数及名称绑定完成了代理/装饰的功能。

还有什么不理想的地方呢?

对,就是query_count = query_count_proxy(query_count),因为这句既不简洁,又属于重复工作。

Python为我们提供了语法糖来完成这类的tedious work。

方法就是:

@query_count_proxy

def query_count(name,age):

return'name is %s, age is %d' %(name,age)

query_count = query_count_proxy(query_count)就等同于在定义query_count函数的时候,在其前面加上@query_count_proxy。

Python看到这样的语法,就会自动的执行query_count = query_count_proxy(query_count)进行name rebinding

补充

以上就是Python实现可调用对象装饰的核心。

可调用对象包括函数、方法、实现了__call__方法的类,上述内容只是针对函数来解释,对于方法、实现了__call__方法的类,其基本原理相同,具体实现略有差别。

Python Decorator 的来龙相关推荐

  1. python中成语接龙游戏_Python实现成语接龙

    这是一篇用Python实现成语接龙小游戏的具体开发教程.Python实现这个功能非常容易,以下分为两个版本,一个是简易版,能够实现基本的功能.还有一个是拓展版,是在简易版上进行拓展,功能更为复杂且完善 ...

  2. 用python实现词语接龙游戏

    用python实现词语接龙游戏 最近,3岁多的女儿很喜欢玩词语接龙.想一想,这个游戏可以通过刚学的python在电脑上实现. 首先是要整理词语库,最好不要太生僻的词语,要够多,才能经得起比赛.经过上网 ...

  3. 用Python 做成语接龙,超简单,有语音,过年和孩子玩

    用Python 做成语接龙,超简单,有语音,过年和孩子玩 成语 需要准备的资料: idiom.json文件 python3.6 安装pyttsx3 pandas numpy 在 https://git ...

  4. python爬取《龙岭迷窟》的数据,看看质量剧情还原度到底怎么样

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:简单 PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行 ...

  5. 关于Python Decorator你应该知道的一切

    转载并整理格式自关于Python Decorator你应该知道的一切 关键词:Python.装饰器.装饰器的深入讨论.Python decorator 前言 最近学习Python,在看一个框架源码过程 ...

  6. 用Python进行诗歌接龙

    目录 实现原理 建立诗歌语料库 诗歌分句 诗歌接龙 测试运行 之前讲解过人工智能对对联项目,本文将展示如何利用Python爬虫来实现诗歌接龙.

  7. python decorator ssh_Python库现后门 可窃取用户SSH信息

    原标题:Python库现后门 可窃取用户SSH信息 导语:Python处理SSH连接的库模块被黑,恶意代码可以收集用户SSH,并发送数据到远程服务器. 研究人员发现Python模块存在后门,注意是py ...

  8. python decorator模块_Python decorator module

    使用functool中的wraps,可以复制一些信息(__name__,__doc__,__module__, __dict__),但是signature还是会被改变(比如参数信息),要保留正确的参数 ...

  9. python decorator. decorator_Python中decorator使用实例

    在我以前介绍 Python 2.4 特性的Blog中已经介绍过了decorator了,不过,那时是照猫画虎,现在再仔细描述一下它的使用. 关于decorator的详细介绍在 Python 2.4中的W ...

  10. python decorator. decorator_decorator在Python中的作用

    decorator(装饰器)在python中作用,可以起到代码复用,也可以起到AOP(面向横切面)的作用. 另外很重要的一点应该就是function在python的世界中是作为一等公民存在的. 在py ...

最新文章

  1. Google BERT模型提取句子Token特征
  2. WSDM 2022 | 一种用于在线广告自动竞价的协作竞争多智能体框架
  3. 【Verilog HDL】从逻辑电路图到门级建模——人工翻译的方法论
  4. 996页阿里Android面试真题解析火爆全网,全网首发!
  5. 从人工智能到云,英特尔开源技术推动软件栈创新
  6. ArrayList 去重
  7. 23矩阵——LU分解、用LU 分解解线性方程组、LU分解的存在性和唯一性、对称矩阵的 L D L 分解、置换矩阵、PA=LU 分解
  8. vue引入bootstrap.min.css报错:Cannot find module ./assets/css/bootstrap.min.css
  9. Android measure过程分析
  10. MySql根据当前页pageNo、显示条数pageSize,实现分页查询的SQL
  11. 【快递100】 物流公司对应编码分享(截止到2021-09-19 最新数据)
  12. 苹果微信更新不了最新版本_微信登录不了,微信提示版本过低,请升级最新版本的解决办法...
  13. LM2596/LM2596S多路降压稳压DC-DC开关电源芯片讲解(第一部分:芯片介绍)(12V转5V、12V转3.3V、任意电压转任意电压)
  14. HTML标签和说明属性
  15. centos7.1 修改selinux相关机制后出现开机失败,报错faild to load selinux policy  freezing
  16. SIGGRAPH 2022 | 基于GAN的新动作合成
  17. 2021-09-27 屏幕尺寸、设计尺寸规范
  18. CES生产函数中参数的意义
  19. 【Elasticsearch源码】CCR源码分析(一)
  20. 图书销售管理系统设计与实现

热门文章

  1. 2020-12.24 用SURF实现简易的两张图像拼接
  2. AlphaGo论文的译文,用深度神经网络和树搜索征服围棋:Mastering the game of Go with deep neural networks and tree search
  3. 页面关闭时postback,导致IE假死的分析
  4. 2021-05-26防火墙配置
  5. android如何虚标内存,答疑 | 手机运存明明是6GB,但实际可用才3.5GB?是虚标还是什么?...
  6. 心灵之火的瞬间-第二则
  7. JetChat-简仿微信聊天应用
  8. 关于阿里云服务器租用费用的介绍
  9. Typecho 主题推荐
  10. 【系统架构】-什么是MDA架构、ADL、DSSA