你必须学写 Python 装饰器的五个理由

你必须学写Python装饰器的五个理由
----装饰器能对你所写的代码产生极大的正面作用
作者:Aaron Maxwell,2016年5月5日
Python装饰器是很容易使用的。任何一个会写Python函数的人都能够学会使用装饰器,比如下面这个:

但是,写出一个装饰器是一个完全不一样的技能。而且这也不是,你不得不理解下面这些:
1、闭包
2、如何将函数作为"第一类"参数来使用
3、变量参数
4、参数解包
5、甚至是Python是如何装载源码的一些细节
所有这些都需要花很多时间去理解和掌握。而且当你已经有这么一堆事情要学的时候,这些值得你花时间吗?
对我来说,这个问题的答案已然是上千次的“肯定,是的,我会学习!”
写装饰器的最重要的好处是什么呢?在你每天的开发中,装饰器让你做什么做起来是很容易并且很强大的呢?
分析、日志以及指导
尤其是在大型软件中,我们通常需要专门来测试到底发生了什么,以及记录那些能量化不同行为的指标。通过在装饰器内部的函数或者方法里面封装这些重要的事件,这个装饰器能通俗易懂且容易地处理刚才这些所讲的需求。比如:

同样的方式可以被用来计数或者其他指标。
验证与运行检查
Python的类型系统是相当类型化了的,但是也是很动态的。对于它的这些所有的好处,也意味着某一些bugs能够悄悄产生,而这些bugs能够在编译的时候被更类型化的语言(比如Java)所捕获。即使更长远看,你可能需要强化更复杂的,在数据进出的时候能个性化检查。装饰器能让你易于处理所有这些,并能一次性地应用它到很多函数上。
假设:你有一堆函数,每个函数都返回一个字典,这个字典包含一个称作“summary”的字段。这个字段的值不能超过80个字符长度;如果违反了,就是不对的。这里给出一个装饰器,当条件不满足的时候它能够抛出一个值错误(ValueError),如下:

创建框架
一旦你掌握了装饰器的编程,你将能够受益于使用装饰器的简单语法,而这让你增加语意给你的代码以便容易使用它。这就是下一个能够扩展Python自身语法的最好的工具。
实际中,很多流行的开源框架都在使用装饰器。网页应用框架Flask就使用了装饰器将URLs的路由交给那些处理HTTPS请求的函数。

在这里,你有一个被叫做app的全局的对象,它有一个被称作route(路由)的方法并接受特定参数。这个路由方法返回一个被应用到处理函数的装饰器。在这个“面罩”下发生了一些很错综复杂的的事情,但是从Flask的使用者角度看,所有这些复杂性是完全被隐藏起来的了。
以这样的方式使用装饰器在stock Python中也有体现。举个例子,完全使用对象系统是有赖于@classmethod和@property装饰器的:

这个类有3个不同的定义声明。但是,他们的语意是各不相同的。
1:constructor是一个正常方法
2:for_winter是一个类方法且提供一种类似于“车间”的东西
3:progess是只读、动态属性
对于日常来说,@classmethod和@property两个装饰器如此简单以致可以很容易扩展Python的对象语意
复用那些不可能复用的代码
Python提供给你一些很强大的工具用以封装代码为一个易用的形式,并带有充分的函数表示语法,支持函数式编程以及全面的对象系统。但是,装饰器也有它所不能捕获的某些形式的代码复用。
比如使用一个不可靠的API。你给那些通过HTTP对话的JSON发出一些请求的时候,API可以99.9%的时候工作正常。但是,有一小部分请求将使得服务器返回一个内部错误,然后你需要重试这些请求。在这个情况下,你将写一个重试逻辑,比如:

现在,假设你有十多个类似于make_api_call的函数,并且他们被所有代码调用。那么你是想要每次调用它们的时候写一个while循环呢?还是每次增加一个API调用函数的时候都把这段代码再写一遍?无论哪种选择都会产生大量的重复代码,除非你用装饰器。用了装饰器事情就简单了。

上述例子可以让你方便使用装饰器@retry
提升你的职业生涯
编写装饰器在一开始并不容易。它虽然不像火箭科学但是也需要你花很多努力去学习,去排除一些细微差异。很多开发者也从来不会通过这些麻烦而学习掌握装饰器编写。但是学习装饰器的确会给你优势。当你是你的团队里面学习如何写好装饰器的那个人的时候,并且你写的装饰器能解决一些实际问题的时候,其他开发者将会使用你的装饰器。因为,一旦这些装饰器编写的困难的部分被完成了,装饰器就会很容易使用。这就对你所写的代码产生极大的正面作用。这也会让你成为一个重要角色。
不论你如何编写装饰器,你会对下面你所要做的事情而感到兴奋,比如你即将能使用装饰器来做一些事情,以及装饰器是如何能永远改变你写Python代码的方式。
英文原文:https://www.oreilly.com/ideas/5-reasons-you-need-to-learn-to-write-python-decorators
译者:gvicky

你必须学写 Python 装饰器的五个理由的更多相关文章
- python 装饰器 第五步(2):带有返回值得装饰器
#第五步:带有返回值的装饰器 把第四步复制过来 #用于扩展基本函数的函数 def kuozhan(func): #内部函数(扩展之后的eat函数) def neweat(): #以下三步就是扩展之后的 ...
- python 装饰器 第五步(1):带有参数的装饰器
#第五步:带有参数的装饰器 #用于扩展基本函数的函数 def kuozhan(func): #内部函数(扩展之后的eat函数) #5由于调用的时候传了两个参数,未来的eat函数没有参数接收 #5报错的 ...
- python 装饰器(五):装饰器实例(二)类装饰器(类装饰器装饰函数)
回到装饰器上的概念上来,装饰器要求接受一个callable对象,并返回一个callable对象(不太严谨,详见后文). 那么用类来实现也是也可以的.我们可以让类的构造函数__init__()接受一个函 ...
- python装饰器(新年第一写)
祭奠碌碌无为的2018,想想其实也不算碌碌无为,至少我还搞懂了装饰器,写了一堆有用没用的玩意 原来觉得装饰器挺难的,直到2018年的最后几天,突然就明白了,难道这就是传说中的开天聪么 言归正传,之所以 ...
- 利用世界杯,读懂 Python 装饰器
Python 装饰器是在面试过程高频被问到的问题,装饰器也是一个非常好用的特性, 熟练掌握装饰器会让你的编程思路更加宽广,程序也更加 pythonic. 今天就结合最近的世界杯带大家理解下装饰器. 德 ...
- http://python.jobbole.com/85056/ 简单 12 步理解 Python 装饰器,https://www.cnblogs.com/deeper/p/7482958.html另一篇文章
好吧,我标题党了.作为 Python 教师,我发现理解装饰器是学生们从接触后就一直纠结的问题.那是因为装饰器确实难以理解!想弄明白装饰器,需要理解一些函数式编程概念,并且要对Python中函数定义和函 ...
- 万恶之源 - Python装饰器及内置函数
装饰器 听名字应该知道这是一个装饰的东西,我们今天就来讲解一下装饰器,有的铁子们应该听说,有的没有听说过.没有关系我告诉你们这是一个很神奇的东西 这个有多神奇呢? 我们先来复习一下闭包 def fun ...
- Python 装饰器入门(上)
翻译前想说的话: 这是一篇介绍python装饰器的文章,对比之前看到的类似介绍装饰器的文章,个人认为无人可出其右,文章由浅到深,由函数介绍到装饰器的高级应用,每个介绍必有例子说明.文章太长,看完原文后 ...
- (二)Python 装饰器
1. 函数 在 Python 中,使用关键字 def 和一个函数名以及一个可选的参数列表来定义函数.函数使用 return 关键字来返回值.定义和使用一个最简单的函数例子: >>> ...
随机推荐
- 网页布局的应用(float或absolute)
一个浮动(左浮动或右浮动) 垂直环绕布局(float.clear) 左右两列布局(float.absolute) 三栏网页宽度自适应布局(float.absolute) 注意:网页设计中应该尽量避免使 ...
- PYTHON 爬虫笔记七:Selenium库基础用法
知识点一:Selenium库详解及其基本使用 什么是Selenium selenium 是一套完整的web应用程序测试系统,包含了测试的录制(selenium IDE),编写及运行(Selenium ...
- 团队作业第5周——测试与发布(Alpha版本)
1.发现的bug a.同时按下和蛇前进方向相反的键和垂直方向的任意一个键贪吃蛇会死亡(比如贪吃蛇向右行走,同时按左上或左下都会game over) b.刷新的苹果会在蛇身上出现 暂时还没能力修复,以后 ...
- Java集合的有序无序问题和线程安全与否问题
首先,清楚有序和无序是什么意思: 集合的有序.无序是指插入元素时,保持插入的顺序性,也就是先插入的元素优先放入集合的前面部分. 而排序是指插入元素后,集合中的元素是否自动排序.(例如升序排序) 1.有 ...
- struts2框架xml验证
struts2验证分为3步: 1.获取需要验证的信息,使用同名属性,提供getter,setter方法.然后框架使用反射将值自动注入. 2.对信息进行验证,成功失败作出对应的选择. xml验证和手动验 ...
- hdu1520树形dp入门
题目链接 题意:要开派对,邀请了上司就不能邀请他的下属,邀请了下属就不能邀请他的上司,每个人有一个值,求邀请的人的总值最大 第一行给出一个数n,代表有n个人. 下面n行分别给出n个人的的值 再下面n行 ...
- C语言中的指针(一)
指针也是一种数据类型,占用内存空间,内存中存储的只能是变量的地址. *p是操作内存的意思,在声明成为指针变量的时候使用*,在使用指针的时候,*表示操作内存. *p放在等号的左边,相当于是从内存中取值, ...
- 网络编程学习笔记-MAC地址和IP地址的关系
简单地说:ip地址是服务商给你的,mac地址是你的网卡物理地址. 一.IP地址 对于IP地址,相信大家都很熟悉,即指使用TCP/IP协议指定给主机的32位地址.IP地址由用点分隔开的4个8八位组构成, ...
- java面试题04
1.就你所熟悉的银行业务面说一下,越详细越好 银行经验:手机银行 网上银行经验 怎么支付 转账 了解基本业务 2.了解工作流的控制,审批流程以及帐务处理么? java中怎么实现工作流.审批流程 ...
- 洛谷 1131 [ZJOI2007]时态同步——树形dp
题目:https://www.luogu.org/problemnew/show/P1131 因为越高,调节一个影响到的越多,所以底下只要把子树间的差异消除了就行了,与其他部分的差异由更高的边调节. ...