Python编程中的反模式

这篇文章收集了我在Python新手开发者写的代码中所见到的不规范但偶尔又很微妙的问题。本文的目的是为了帮助那些新手开发者渡过写出丑陋的Python代码的阶段。为了照顾目标读者,本文做了一些简化(例如:在讨论迭代器的时候忽略了生成器和强大的迭代工具itertools)。

对于那些新手开发者,总有一些使用反模式的理由,我已经尝试在可能的地方给出了这些理由。但通常这些反模式会造成代码缺乏可读性、更容易出bug且不符合Python的代码风格。如果你想要寻找更多的相关介绍资料,我极力推荐The Python TutorialDive into Python

Python编程中的反模式

《Python核心编程 第二版》.(Wesley J. Chun ).[高清PDF中文版]

《Python开发技术详解》.( 周伟,宗杰).[高清PDF扫描版+随书视频+代码]

Python脚本获取Linux系统信息

Ubuntu下用Python搭建桌面算法交易研究环境

迭代

range的使用

Python编程新手喜欢使用range来实现简单的迭代,在迭代器的长度范围内来获取迭代器中的每一个元素:

for i in range(len(alist)): print alist[i]

应该牢记:range并不是为了实现序列简单的迭代。相比那些用数字定义的for循环,虽然用range实现的for循环显得很自然,但是用在序列的迭代上却容易出bug,而且不如直接构造迭代器看上去清晰:

for item in alist: print item

range的滥用容易造成意外的大小差一(off-by-one)错误,这通常是由于编程新手忘记了range生成的对象包括range的第一个参数而不包括第二个,类似于java中的和其他众多这种类型的函数。那些认为没有超出序列结尾的编程新手将会制造出bug:

# 迭代整个序列错误的方法 alist = ['her', 'name', 'is', 'rio'] for i in range(0, len(alist) - 1): # 大小差一(Off by one)! print i, alist[i]

不恰当地使用range的常见理由:

1. 需要在循环中使用索引。这并不是一个合理的理由,可以用以下方式代替使用索引:

for index, value in enumerate(alist): print index, value

2. 需要同时迭代两个循环,用同一个索引来获取两个值。这种情况下,可以用来实现:

for word, number in zip(words, numbers): print word, number

3. 需要迭代序列的一部分。在这种情况下,仅需要迭代序列切片就可以实现,注意添加必要的注释注明用意:

for word in words[1:]: # 不包括第一个元素 print word

有一个例外:当你迭代一个很大的序列时,切片操作引起的开销就比较大。如果序列只有10个元素,就没有什么问题;但是如果有1000万个元素时,或者在一个性能敏感的内循环中进行切片操作时,开销就变得非常重要了。这种情况下可以考虑使用代替range [1]。

在用来迭代序列之外,range的一个重要用法是当你真正想要生成一个数字序列而不是用来生成索引:

# Print foo(x) for 0<=x<5 for x in range(5): print foo(x)

正确使用列表解析

如果你有像这样的一个循环:

# An ugly, slow way to build a list words = ['her', 'name', 'is', 'rio'] alist = [] for word in words: alist.append(foo(word))

你可以使用列表解析来重写:

words = ['her', 'name', 'is', 'rio'] alist = [foo(word) for word in words]

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/6cf98f833d23e9cd8ab458345986043f.html