Tinyfool@Csdn

天行健,君子以自强不息----本Blog内容均可转载,但是作者不放弃版权,转载必须标明作者和原文地址。

用户操作
[留言]  [发消息]  [加为好友] 
订阅我的博客
XML聚合    FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
tinydust的公告
<div style="text-align:center;"> <script type="text/javascript"><!-- google_ad_client = "pub-7732761529337293"; google_ad_width = 160; google_ad_height = 600; google_ad_format = "160x600_as"; google_ad_type = "text_image"; //2007-02-17: tinydust@csdn google_ad_channel = "3723841443"; //--></script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script> <a href="http://www.codechina.org/bbs/"> <span style="font-family: 'Lucida Sans','Century Gothic',SimHei,Sans-Serif; font-size: 17pt; display: block; margin-bottom: 2px; font-weight: bold;"> <span style="color: rgb(0, 70, 189);">C</span><span style="color: rgb(214, 40, 9);">o</span><span style="color: rgb(0, 70, 189);">d</span><span style="color: rgb(59, 172, 58);">e</span><span style="color: rgb(245, 207, 66);">C</span><span style="color: rgb(214, 40, 9);">h</span><span style="color: rgb(0, 70, 189);">i</span><span style="color: rgb(59, 172, 58);">n</span><span style="color: rgb(0, 70, 189);">a</span><span style="color: rgb(59, 172, 58);">.</span><span style="color: rgb(214, 40, 9);">O</span><span style="color: rgb(59, 172, 58);">r</span><span style="color: rgb(214, 40, 9);">g</span></span> <span style="font-size: 7pt;">中国代码网-中国程序员的代码天堂</span> </a><br/> <h2> <a href="http://www.ginkgotek.com/">银杏泰克科技有限公司[站内搜索解决方案]</a></h2> <a href="http://www.zmap.org/">全能之眼</a><br/> <a href="http://www.flickr.com/photos/chinapodcast/64465870/" title="Photo Sharing"><img src="http://static.flickr.com/28/64465870_c1f95649a3_t.jpg" width="100" height="75" alt="Tiny同志在配眼镜" /></a> <h3><a href="http://www.tinydust.net/">微尘程序员网站</a></h3> </div>
文章分类
Tinyfool
Tinyfool的开发日记(RSS)
Tinyfool的移动开发阵线(RSS)
Tinyfool的随想录(RSS)
微尘程序员网站
联系Tinyfool
存档

原创  一个Python程序的6次改进 收藏

有位朋友用CString类写了一个Email列表去重程序,结果发现处理78000 行的数据居然用了7分多种。于是他用Python的map(hash实现的)重写了这个程序,最后只用了300ms。CString一定会慢,因为实现中 没有使用hash。于是有人用c写了一个hash函数来实现这个功能,最后花了400ms。但是代码长度是Python代码的数十倍。详情请看这里hashtable功能也实现了这个功能,速度超过了Python,但是代码也很简洁。qyb说,“这个例子再一次教育我们,熟练掌握优秀的第三方库是多么的重要.”

我这里没有现成的gcc和glib,不好测试qyb的程序。但是仅就那个用来测试Python程序来说,存在很多降低效率的误区,所以,我把这些问题都用效率更加的方式改写了,从而把程序的效率提高了三倍左右,现在与大家分享。

原程序:运行时间0:00:00.609000
import datetime

if __name__ == "__main__":
t1=datetime.datetime.today()
hashtable = {}
f = file("email.txt","r")
f2 = file("email_new.txt","w")
line = f.readline();
while len(line)>0:
if not hashtable.has_key(line):
hashtable[line] = 1
f2.write(line)
line = f.readline();
f.close()
f2.close()
t2=datetime.datetime.today()
print str(t2-t1)


显而易见,用f.readline()是不明智的,这样输入速度大减。我们用readlines()来加速。
改进一:运行时间0:00:00.375000
import datetime

if __name__ == "__main__":
t1=datetime.datetime.today()
hashtable = {}
f = file("email.txt","r")
f2 = file("email_new.txt","w")
lines = f.readlines()
for line in lines:
if not hashtable.has_key(line):
hashtable[line] = 1
f2.write(line)
f.close()
f2.close()
t2=datetime.datetime.today()
print str(t2-t1)

然 后我们看输出,很显然f2.write(line)也是很不明智的,一行一行的输出无论如何都是低效的。writelines可以解决这个问题,我们知道 map的keys()函数可以返回map的键列表,所以, f2.writelines(hashtable.keys())看来是个好选择。
改进二:运行时间0:00:00.281000

import datetime

if __name__ == "__main__":
t1=datetime.datetime.today()
hashtable = {}
f = file("email.txt","r")
f2 = file("email_new.txt","w")
lines = f.readlines()
for line in lines:
if not hashtable.has_key(line):
hashtable[line] = 1
f.close()
f2.writelines(hashtable.keys())
f2.close()
t2=datetime.datetime.today()
print str(t2-t1)

实际上我们知道采用hashtable[line] = 1方式的时候,如果键已经存在,仅仅会更新键的值而已。所以判断语句if not hashtable.has_key(line)实际上是无用的,应该去掉。
改进三:运行时间0:00:00.250000

import datetime

if __name__ == "__main__":
t1=datetime.datetime.today()
hashtable = {}
f = file("email.txt","r")
f2 = file("email_new.txt","w")
lines = f.readlines()
for line in lines:
hashtable[line] = 1
f.close()
f2.writelines(hashtable.keys())
f2.close()
t2=datetime.datetime.today()
print str(t2-t1)


到这里我们发现另外一个问题,我们实际上只需要map的键,而不需要它的值。所以我们直接用操作map的键列表的方式应该可以加速程序的运行。幸好,运行的结果证明了我的推论。
改进四:运行时间0:00:00.188000

import datetime
if __name__ == "__main__":
t1=datetime.datetime.today()
hashtable = {}
f = file("email.txt","r")
f2 = file("email_new.txt","w")
lines = f.readlines()
for line in lines:
hashtable.keys().append(line)
f.close()
f2.writelines(hashtable.keys())
f2.close()
t2=datetime.datetime.today()
print str(t2-t1)

然后,我遭遇了一个小挫败,我记得有人告诉过我用map函数处理列表应该比for in方式更加高效。但是运行结果没有遵循这个说法,也许是我哪里写错了。不过至少map和lamdba可以让程序看起来简洁一些,或者说更酷,更加让人难懂,哈哈。
改进五:运行时间0:00:00.250000

import datetime
if __name__ == "__main__":
t1=datetime.datetime.today()
hashtable = {}
f = file("email.txt","r")
f2 = file("email_new.txt","w")
lines = f.readlines()
map(lambda x:hashtable.keys().append(x),lines)
f.close()
f2.writelines(hashtable.keys())
f2.close()
t2=datetime.datetime.today()
print str(t2-t1)

这个方法不是我写的,而是qyb文章后一个匿名网友的留言。应该说这个方法我没有想到的主要原因是我确实不知道set类型,-____-#。这个方法无疑是最简洁的一种,虽然效率不如我的第四种改进方式,也许这是因为一些实现上的问题造成的。
改进六:运行时间0:00:00.219000

import datetime

if __name__ == "__main__":
t1=datetime.datetime.today()
f = file("email.txt","r")
f2 = file("email_new.txt","w")
f2.write("".join(set(f.readlines())))
f.close()
f2.close()
t2=datetime.datetime.today()
print str(t2-t1)


我的结论很简单,Python真的很好用,呵呵。 

发表于 @ 2006年07月16日 23:40:00 | 评论( loading... ) | 编辑| 举报| 收藏

旧一篇:什么是BOINC? | 新一篇:Web应用和PC端软件开发的共同趋势是并行

  • 发表评论
  • 评论内容:
  •  
Copyright © tinydust
Powered by CSDN Blog