BLOG
Enjoy when you can, and endure when you must.
MAR 29, 2016/Python
提防黑盒子:关注 Python 使用中的细节(一)

Python 是一门非常有趣的语言,他为我们准备了大量的组件,让我们的开发工作更加轻松。但这些组件有时候也因为这样的“黑盒子”特性而成为一种风险,必须时刻提防。本文整理在开发、学习过程中遭遇、瞥见或收集到的一些“危险”场景。

 

隐性平方级操作:item in LIST vs item in SET

from random import randrange

l = [randrange(10000) for I in range(10000)]
12 in l

s = set(l)
12 in s

如以上的代码,在一个列表中查询 12 和在一个集合中查询 12 乍一看好像别什么太大的区别,但在某些时候可能是千差万别的。列表是一个顺序结构,如果要在列表中查询一个元素,则需要对列表进行一次迭代以确定元素是否存在,因此成员查询对于列表来说是线性级的。而集合的底层实现在 Python 中是哈希表,这也就意味着成员查询对于集合来说则是常数级的。由此可以看出,如果打算进行多次成员查询操作,且列表元素相对庞大的时候,这就变成了一个隐性的平方级操作。这时考虑将其转化为集合,再完成所需的查询操作,可能会是一个更好的选择。

 

构建字符串的陷阱

d = ''
for chunk in string_producer():
    d += chunk

以上代码可以说是我们的惯用手法,并且一般情况下都不会存在太大问题。但如果想象一下 chunks 的规模如果非常大的话会有什么后果?在 Python 中,字符串属于不可变对象,也就意味着对字符串做加法操作,实际是在新建字符串。因此非常规情况下这样的操作可能会非常慢。这种时候以下方法的效果会更好:

chunks = []
for chunk in string_producer()]:
    chunks.append(chunk)
d = ''.join(chunks)

列表的 append 操作允许将原有空间加上一定的百分比来进行“过度”分配,其可用空间的增长方式是指数式的,这是,append 操作的成本在交由所有操作平均承担(均摊)的情况下就变成了常数级的操作。

COMMENTS
LEAVE COMMNT