编写高质量代码–改善python程序的建议(二)
原文发表在我的博客主页,转载请注明出处!
建议七:利用assert语句来发现问题
断言(assert)在很多语言中都存在,它主要为调试程序服务,能够快速方便地检查程序的异常或者发现不恰当的输入等,可防止意想不到的情况出现。其语法如下:
assert expression1 ["," expression2]
其中expression1的值会返回True或者False,当值为False的时候会引发AssertionError,而expression2是可选的,常用来传递具体的异常信息。
不过断言是有代价的,它会对性能产生一定的影响,对于编译型的语言,如C/C++,这也许并不那么重要,因为断言只在调试模式下启用。但python并没有严格定义调试和发布模式之间的区别,断言是被设计用来捕获用户所定义的约束的,而不是用来捕获程序本身的错误的,因此在使用时需要注意:
- 不要滥用,若由于断言引发了异常,通常代表程序中存在bug,因此断言应该使用在正常逻辑不可到达的地方或正常情况下总是为真的场合
- 如果python本身的异常能够处理就不要使用断言。如类似于数组越界、类型不匹配、除数为0之类的错误,不建议使用断言。
- 不要使用断言来检查用户的输入
- 在函数调用后,当需要确认返回值是否合理时可以使用断言
- 当条件是业务逻辑继续下去的先决条件时可以使用断言
建议八:数据交换值的时候不推荐使用中间变量
在python中,更pythonic的实现数值交换的方式为:
x,y = y,x
不论从执行效率和代码简洁程度上来说,这种数值交换都是非常具有优势的。python的表达式计算的顺序一般情况下是从左到右,但遇到表达式赋值的时候表达式右边的操作数先于左边的操作数计算,因此对于上面的表达式,其在内存中执行的顺序如下:
1. 先计算右边的表达式y,x,因此先在内存中创建元祖(y,x)
2. 计算表达式左边的值并进行赋值,元祖被依次分配给左边的标识符,通过解压缩(unpacking),元祖第一标识符(为y)分配给左边第一个元素(x),第二个类似,这样达到x,y值交换的目的。
建议九:充分利用Lazy evaluation的特性
Lazy evaluation常被翻译为“延迟计算”或“惰性计算”,指的是仅仅在真正需要执行的时候才计算表达式的值,有两个好处:
- 避免不必要的计算,带来性能上的提升.比如与运算在第一项为false的情况下就不会再计算后面的。
- 节省空间,使得无限循环的数据结构成为可能。python中最典型的使用延迟计算的例子就是生成器表达式了,它仅在每次需要计算的时候才通过yield产生所需要的元素。比如斐波那契数列,while True不到无限循环。
def fib():
a, b = 0, 1
while True:
yield a
a, b = b, a+b
建议十:理解枚举替代实现的缺陷
1. 使用类属性
class Seasons:
Spring, Summer, Autumn, Winter=range(4)
2. 借助函数
def enum(*posarg, **keysarg):
return type("Enum", (object,), dict(zip(posarg, xrange(len(posarg))), **keysarg))
Seasons = enum("Spring", "Summer", "Autumn", Winter=1)
3. 使用collections.namedtuple
Seasons = namedtuple(‘Seasons’, ‘Spring Summer Autumn Winter’)._make(range(4))
建议十一:不推荐使用type来进行类型检查
内建函数type(object)用于返回当前对象的类型,因此可以通过与python自带模块types中所定义的名称进行比较,根据其返回值确定变量类型是否符号要求。例如判断一个变量a是不是list类型可以使用如下代码:
if type(a) is types.ListType:
所有基本类型对应的名称都可以在types模块中找到,如types.BooleanType、types.IntType、types.StringType、types.DictType等。但是为什么不推荐使用type来进行变量类型检查呢。
- 首先,发现基于内建类型(比如int)扩展的用户自定义类型,type函数并不能准确返回结果。
- 在古典类中,任意类的实例的type()返回结果都是,这种情况下使用type()函数来确定两个变量类型是否相同显然结果会与我们所理解的不同。 所以为了约束用户的输入类型从而使之与我们期望的类型一致,如果类型有对应的工厂函数,可以使用工厂函数对类型做相应转换,如list(listing)、str(name)等。否则可以使用isinstance()函数来检测,如下:
isinstance(object, classinfo)
#其中,classinfo可以为直接或间接类名、基本类型名称或者由它们组成的元祖
#isinstance(2, float) False
#isinstance("a", (str,unicode)) True
建议十二:尽量转换为浮点类型后再做出发
当涉及除法运算的时候尽量先将操作数转换为浮点类型的再做运算,比如:
a = float(4*3)/float(12*7)
不过python3已经不存在这个问题了,可以通过下面的语句使整数除法不再截断
from __future__ import division
另外需要注意对于浮点数的处理,其运算结果可能并不是完全准确的。
总结:编程语言通常都有其惯用法,掌握上面所述的这些惯用法是非常必要的。如果计算对精度要求较高,可以使用decimal来进行处理或者将浮点数尽量扩大为整数,计算完毕之后再转换回去,同时浮点数的比较同样最好能够指明精度。
参考:编写高质量代码–改善python程序的91个建议
编写高质量代码–改善python程序的建议(二)的更多相关文章
- 编写高质量代码--改善python程序的建议(六)
原文发表在我的博客主页,转载请注明出处! 建议二十八:区别对待可变对象和不可变对象 python中一切皆对象,每一个对象都有一个唯一的标识符(id()).类型(type())以及值,对象根据其值能否修 ...
- 编写高质量代码--改善python程序的建议(八)
原文发表在我的博客主页,转载请注明出处! 建议四十一:一般情况下使用ElementTree解析XML python中解析XML文件最广为人知的两个模块是xml.dom.minidom和xml.sax, ...
- 编写高质量代码--改善python程序的建议(七)
原文发表在我的博客主页,转载请注明出处! 建议三十四:掌握字符串的基本用法 编程有两件事,一件是处理数值,另一件是处理字符串,在商业应用编程来说,处理字符串的代码超过八成,所以需要重点掌握. 首先有个 ...
- 编写高质量代码–改善python程序的建议(五)
原文发表在我的博客主页,转载请注明出处! 建议二十三:遵循异常处理的几点基本原则 python中常用的异常处理语法是try.except.else.finally,它们可以有多种组合,语法形式如下: ...
- 编写高质量代码--改善python程序的建议(四)
原文发表在我的博客主页,转载请注明出处! 建议十八:有节制的使用from...import语句 python提供了三种方式引入外部模块: import语句 from...import... __imp ...
- 编写高质量代码--改善python程序的建议(三)
原文发表在我的博客主页,转载请注明出处! 建议十三:警惕eval()的安全漏洞 相信经常处理文本数据的同学对eval()一定是欲罢不能,他的使用非常简单: eval("1+1==2" ...
- 编写高质量代码--改善python程序的建议(一)
原文发表在我的博客主页,转载请注明出处! 初衷 python是一个入门十分容易的编程语言,但是想要写好python却是一件不容易的事情,如果不是专业使用python的人,只是将python作为一个脚本 ...
- 编写高质量代码改善python程序91个建议学习01
编写高质量代码改善python程序91个建议学习 第一章 建议1:理解pythonic的相关概念 狭隘的理解:它是高级动态的脚本编程语言,拥有很多强大的库,是解释从上往下执行的 特点: 美胜丑,显胜隐 ...
- 编写高质量代码 改善Python程序的91个建议 (读后 小记)
此书是自己好久之前买的,当时总觉得Python语言中有各种trick, 总是要自己猝不及防的掉入到陷阱之中, 看了一些资料后发现了这本书,感觉很是不错,不过可惜自己平时总是杂事太多,总是找不到整块的时 ...
随机推荐
- 学习-短信的上行(MO)和下行(MT)详解
基础知识: SP服务提供商: 通常是指在移动网内运营增值业务的社会合作单位, 它们建立与移动网络建立相连的服务平台, 为手机用户提供一系列信息服务, 如:娱乐.游戏.短信.彩信.WAP.彩铃.铃声下载 ...
- Latex排版:CTeX winEdit 输出“系统找不到指定的文件”的解决办法)
winEdit输出“系统找不到指定的文件”,这里“指定的文件”是“TeXify.exe”等需要运行的程序,而不是当前需要编译的“.tex”文件.所以,问题的本质就是系统找不到“TeXify.exe”等 ...
- centos 7 生成文件名乱码的问题如何解决?
在应用脚本生成文件时,发现生成的文件名称出现乱码(似麻将一样).刚开始找来找去,以为是复制粘贴的原因,复制时复制了特殊字符导致的,结果修改源文件后发现生成的文件名还是乱码.后来在执行脚本时,提示&qu ...
- unity, 不要试图用rigidbody.Sleep()停止rigidbody
如果想让rigidbody pause,用rigidbody.Sleep()是完全错误的办法.因为有很多情况都可能使一个处在sleep的rigidbody唤醒,所以调用rigidbody.Sleep( ...
- unity, Global和Local编辑模式
下图表示是在Local模式下: 下图表示是在Global模式下: 不要搞反.
- Spark缓存机制
虽然默认情况下 RDD 的内容是临时的,但 Spark 提供了在 RDD 中持久化数据的机制.第一次调用动作并计算出 RDD 内容后,RDD 的内容可以存储在集群的内存或磁盘上.这样下一次需要调用依赖 ...
- apache与和mysql重启命令
修改linux服务器的http配置之后,必须重启Apache服务. 命令为: /etc/rc.d/init.d/httpd restart chown -R mysql:mysql 目录名 改变文件属 ...
- Atitit.js模块化 atiImport 的新特性javascript import
Atitit.js模块化 atiImport 的新特性javascript import 1. 常见的js import规范amd ,cmd ,umd1 1.1. Require更多流行3 2. at ...
- Apollo配置中心转
尊重原创,本文转自:https://www.cnblogs.com/FlyAway2013/p/8811385.html 前我们项目,所有的配置基本都是通过本地properties 文件进行配置的,比 ...
- makefile之命令包&多行变量
define&endef 1. 命令包(canned recipes)&多行变量(muti-line variables) The define directive is follow ...