追求效率的时候,就该斤斤计较
之前
因为以前写代码从来都是自己玩的,不需要细致入微地考虑效率问题,再加上学 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) 收藏 举报
浙公网安备 33010602011771号