核心知识点:

1.用None这个返回值来表示特殊意义的函数,很容易使调用者犯错,因为None和0以及空字符串之类的值,在条件表达式里都会评估为False。

2.两种方法:二元法;将异常抛给上一级直接报错。

编写工具函数(utility function)时,我们有时候喜欢给None这个返回值赋予特殊意义,有时候这么做是合理地,有时候就会出错。

例如要编写辅助函数,计算两数相除的商,在除数为0的情况下,计算结果是没有明确含义的,所以似乎应该返回None,就像下面这样:

In [1]: def divide(a,b):
...: try:
...: return a / b
...: except ZeroDivisionError:
...: return None
...:
#貌似没有什么问题
#执行几次试试
In [2]: divide(1,2)
Out[2]: 0.5 In [3]: divide(1,0) In [4]: divide(0,1)
Out[4]: 0.0

貌似是没有什么问题,但是当在if语句中拿这个计算结果做判断时,会出现问题。

我们可能不会专门去判断函数的返回值是否为None,而是:只要返回与False等效的运算结果,就说明函数出错了。

这样明显有漏洞,当a=0,函数没有报错,但是按照上面的逻辑却是会报错。

如果None这个返回值,对函数有特殊意义(在上面的例子中,None的特殊意义就是异常),那么在编写Python代码时,就很容易犯上面这种错误。

有两种方法可以减少这种错误:

第一种方法,是把返回值拆成两部分,并放到二元组(two-tuple)里面。二元组的首个元素表示操作是否成功,接下来的那个元素,才是真正的运算结果。

In [9]: def divide(a,b):
...: try:
...: return True,a / b
...: except ZeroDivisionError:
...: return False, None
...: In [10]: divide(1,0)
Out[10]: (False, None) In [11]: divide(0,1)
Out[11]: (True, 0.0)

调用该函数的人需要解析这个元祖。这就使得不能只根据结果来遐想了,而必须根据运算状态的那个元素来做判断。

第二种办法更好一些,那就是根本不返回None,而是把异常把异常抛给上一级,使得调用者必须应对它。

In [13]: def divide(a,b):
...: try:
...: return a / b
...: except ZeroDivisionError as e:
...: raise ValueError('Invalid inputs') from e
...:

调用者需要处理因输入值无效而引发的异常。

调用者无需用条件语句来判断函数的返回值,因为如果函数没有抛出异常,返回值自然就是正确的,这样写出来的异常处理代码,也比较清晰。

第14条:尽量用异常来表示特殊情况,而不要返回Nono的更多相关文章

  1. web前端性能14条规则

    14条规则 1.减少Http请求 使用图片地图 使用CSS Sprites 合并JS和CSS文件 这个是由于浏览器对同一个host有并行下载的限制,http请求越多,总体下载速度越慢 2.使用CDN( ...

  2. 雅虎Yahoo 前段优化 14条军规

    Yahoo 14条 雅虎十四条 腾讯前端设计的Leader推荐我背熟的.请大家都能好好学习,不要像我一样一扫而过,好好的记下来!不仅仅是晓得一些CSS xhtml就好了,深刻认识到很多的东西需要学习的 ...

  3. 对ios、android开发程序员的14条忠告

    ————————本文摘自千锋教育(http://www.mobiletrain.org/)对ios\android开发程序员的14条忠告————————— 1.不要害怕在工作中学习. 只要有电脑,就可 ...

  4. [译] MVP模式的14条规则

    笔者在前文<MVP和MVC>中提到了两者的区别,以及MVP日趋流行的原因:即随着各种给力UI框架的发布,View的功能越来越强,已经足以完成一些简单的不需要与后台或其他view交互的eve ...

  5. 14条最佳JS代码编写技巧

    http://gaohaixian.blog.163.com/blog/static/123260105201142645458315/写任何编程代码,不同的开发者都会有不同的见解.但参考一下总是好的 ...

  6. DIV+CSS常见问题的14条原因分析

    当你在一个浏览器里面做好,在其他浏览器里面却完全不是那么回事情.  很多时候,我们就只是去修补下,或者利用各个浏览器对代码支持的不一致,进行针对各个浏览器进行不同的定义.  其实浏览器的不兼容,我们往 ...

  7. autowire异常的三个情况

    2010-3-11 16:06:00 net.sf.ehcache.config.ConfigurationFactory parseConfiguration 警告: No configuratio ...

  8. YaHoo Web优化的14条法则

    Web应用性能优化黄金法则:先优化前端程序(front-end)的性能,因为这是80%或以上的最终用户响应时间的花费所在. 法则1. 减少HTTP请求次数 80%的最终用户响应时间花在前端程序上,而其 ...

  9. 【php】页面加载优化的14条原则

      1. 尽可能的减少 HTTP 的请求数 [content] 2. 使用 CDN(Content Delivery Network) [server] 3. 添加 Expires 头(或者 Cach ...

随机推荐

  1. select、poll、epoll之间的区别总结[整理](转)

    select,poll,epoll都是IO多路复用的机制.I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作.但select ...

  2. int a[3];中a+1与&amp;a+1差别 -- C

    int a[3]; a 和 &a 的地址一样的. a+1 == a + 1*sizeof(int);跳跃是一个数组元素大小 &a+1 == a + 3*sizeof(int);跳跃是整 ...

  3. Java自动内存管理机制

    1.运行时数据区域划分 2.程序计数器 作用:可以看做是当前线程所执行的字节码的行号指示器. 解释:字节码指示器就是通过改变程序计数器的值来指定下一条需要执行的指令.分支,循环等 基础功能就是依赖程序 ...

  4. html头部转码

    学习html是件比较容易的事情,但单单学html语言肯定是不够用的,所以大多数人并没有拿html作为学习核心,而是将html作为javascript.动态语言或者css学习的必经之路.于是很多人并不关 ...

  5. 两个页面相同js方法兼容

    1. a.js页面 //Js获取Url参数 function request(paras) { var url = location.href; var paraString = url.substr ...

  6. 【Hadoop基础教程】4、Hadoop之完全分布式环境搭建

    上一篇blog我们完成了Hadoop伪分布式环境的搭建,伪分布式模式也叫单节点集群模式, NameNode.SecondaryNameNode.DataNode.JobTracker.TaskTrac ...

  7. Python基础之初识递归

    初识递归 递归的定义: 在一个函数里再调用这个函数本身,这种魔性的使用函数的方式就叫做递归. 递归的最大深度--997 递归函数不受外力的阻止会一直执行下去,python为了杜绝此类现象,强制将递归层 ...

  8. Arcgis:坐标系统极其转换

    1. ArcGIS中的坐标系统 ArcGIS中预定义了两套坐标系统,地理坐标系(Geographic coordinate system)和投影坐标系(Projectedcoordinate syst ...

  9. WPF的TextBox抛出InvalidOperationException异常:Cannot close undo unit because no opened unit exists.

    近期遇到一个问题.应用使用过程中突然崩溃,查看dump发现异常信息例如以下: UI dispatcher has encountered a problem: 无法关闭撤消单元.由于不存在已打开的单元 ...

  10. applicationContext-XXX.xml和XXX-servlet.xml的区别

    1.ApplicationContext.xml  是spring 全局配置文件,用来控制spring 特性的 2.dispatcher-servlet.xml 是spring mvc里面的,控制器. ...