追求效率的时候,就该斤斤计较

之前

因为以前写代码从来都是自己玩的,不需要细致入微地考虑效率问题,再加上学 Python 的时候其实并没有去了解多少它底层的实现,所以写起代码来,也很随意。

这次遇到一个大问题,对一批数据进行清洗,把sql中得到的一个个 set 的数据统计成 2 个 dict 和一个 list 嵌套的形式,本来感觉就是很简单的查询和统计操作,应该会很快处理完吧。

事实上,就是这么简单的操作,加上都是 Python 基本的数据结构,不同的代码在效率上也有着天壤之别。

对比

1 data = {}
2 for line in sql:
3     other = line[2:]
4     if line[0] not in data.keys():
5         data[line[0]] = {}
6     if line[1].date() not in data[line[0]].keys():
7         data[line[0]][line[1].date()] = []
8     data.[line[0]][line[1].date()].append(other)

修改后为:

 1 data = {}
 2 for line in sql:
 3     uid = line[0]
 4     dat = line[1].date()
 5     other = line[2:]
 6     if uid not in data:
 7         data[uid] = {}
 8     if dat not in data[uid]:
 9         data[uid][dat] = []
10     data.[uid][dat].append(other)

分析

整体来看,就是用临时变量替换了6个简单的查询,但是实际效果确提升了很多。

前后耗时对比
修改前 356.316s
修改后 0.360s

 

 

 

 

这个结果看上去真的有些夸张……

上面这个图说明,这个时候不要用 dict.keys(),因为这个操作其实是 copy 了一份 key 给你用的,用在这里并不恰当,详情参考这里:http://stackoverflow.com/questions/17634177/why-use-dict-keys

然后那个日期取 .date() 操作,一般这种字符串操作都会耗时,所以最好提前做

总结一下就是说,循环里面能提前初始化的就初始化,减少 copy 和字符串操作,Python 一般对 if/in、for/in 之类的操作会有一些优化,效率较高

后记

当时遇到这个问题的时候,还想着自己要不要去看下 Python 的源代码……

后来找了下 Python 基本数据结构的时间复杂度https://wiki.python.org/moin/TimeComplexity,发现没什么问题啊

然后我还考虑去搞一波 Pandas,因为里面是各种类型的数据,没办法用 Numpy,当然这个还是需要后面继续做的。

其实还是自己经验不够,一开始就应该做一下效能分析的,然后就能快速定位问题了……这是个教训

posted on 2016-11-07 17:26  MomingCoder  阅读(562)  评论(0)    收藏  举报

导航