python 程序优化的技巧及小知识点

1 在作比较时你可以这样写: 3.14<pi<3.15,它得到的结果和(pi>3.14 and pi<3.15)是一样的,在大多数其他语言里,你都不能用这么自然的语法了。

2 Int类型不会在超过31bit或32bit后溢出,它们会变成long型。在
python里,long并非就是64位,他就是"长"类型,(python的长类型可以容纳数万位大的整数),效率会降低一点。在python 3000中,甚至连int与long的区别都没有了。

3默认值只会在编译时被赋值一次,而非运行时。试试这个: def func
(a[]): a.append(42); 返回值a会随调用不断加入42. python的教程里有更多相关的讨论。

4 连接多个字符串时,"".join(list)会比 for x in list: s+=x快得多。实际上 join调用复杂度是o(n),而+=是o(n2).有很多人要求使这个调用更快,而且python2.5里似乎也应该变得更快了,但我的测试结果

却并非如此,有谁知道为什么吗?

5 语法 print >>file里,仅数值被写入文件中,而print的格式化功能不起作用。我很高兴听到他们说在python 3000总,print会变成一个函数,而且带有了更多高级的特性。

6 你可以通过(x,)来创建只有一个元素的tuple,通常你只能建立如
(x,y,z)那样的tuple,如果你想通过(x)来建立一个tuple,得到的只是x

7如果你想看看整数类的帮助文档,你可以写(5).__str__; 你不能简化成5.__str__,因为解释器会把5.认作是浮点数,然后出错了。

8你可以使用属性而不是getter或setter函数。例如serial. baudrate=192000 可以设置serial._baud,跟你调用其它调用的效果一样。

9 一个紧跟在for循环后的else语句只有在循环不通过break退出时才会被调用。这对查找循环很有用处,通常这样的循环都会需要在退出后作
额外的检查判断。 

判断字典存不存在key

if key in _dict:
  ...cost time : 0.000270260584074

if key in _dict.keys():
  ...cost time : 0.05606396371
效率高...

上面是1000000数据测试

 

''''' 去除重复元素 '''  l1 = ['b','c','d','b','c','a','a']  l2 = list(set(l1))  print l2    l3 = [('a','b','dddd'), ('a','b','dddd'),('a','b','dddd1')]  print {}.fromkeys(l3).keys()  


a = 1  b = 2  #如何交接两个变量的值:    a,b = b,a  

python去掉回车符 换行符 空格

s=’   as asdas \r\nasda’
print ”.join(s.split())

 

 

 

 

python 提高效率的几个小技巧

1.1. 最常见
一个最常见的速度陷坑(至少是俺在没看到网上这篇介绍时陷进去
过好些次的) 是: 许多短字串并成长字串时, 大家通常会用:

Toggle line numbers
   1 shortStrs = [ str0, str1, ..., strN]
   2 #N+1个字串所组成的数列
   3 longStr = ”
   4 for s in shortStrs: longStr += s
因为Python里 字串是不可变的, 所以每次 longStr += s 都是将原 来的 longStr 与 str 拷贝成一个新字串, 再赋给longStr. 随着 longStr的不断增长, 所要拷贝的内容越来越长. 最后导至str0被 拷贝N+1次, str1是N次, … .

那咋办呢 ? 咱们来看看Skip Montanaro先生的解说: http://musi-cal.mojam.com/~skip/python/fastpython.html 及可参考一下Guido van Rossum本人的: http://www.python.org/doc/essays/list2str.html

1.1.1. 找出速度瓶颈
1)首先在大家应先学会怎么去找出速度瓶颈: Python自带有profile
模块:

Toggle line numbers
   1 import profile
   2 profile.run (’想要检查的函数名()’)
就会打印出那个函数里调用了几次其它函数, 各用了多少时间, 总共用了多少时间等信息 — Nice ? 详请参阅<<库参考>>中的 profile模块的论述.

当然脑袋笨一点或是聪明一点的, 也可以用time模块中的time() 来显示系统时间, 减去上次的time()就是与它的间隔秒数了.

1.1.2. 字串相并
就头上的例子而言, 用 :

Toggle line numbers
   1 longStr =”.join(shortStrs)
立马搞定, 但如果shortStrs里面不都是字串, 而包含了些数 字呢 ? 直接用join就会出错. 不怕, 这样来:

Toggle line numbers
   1 shortStrs = [str(s) for s in shortStrs[i]]
   2 longStr = ”.join(shortStrs)
也即先将数列中所有内容都转化为字串, 再用join.

对少数几个字串相并, 应避免用: all = str0 + str1 + str2 + str3 而用: all = ‘%s%s%s%s’ % (str0, str1, str2, str3)

1.1.3. 数列排序
list.sort ()
你可以按特定的函数来: list.sort( 函数 ), 只要这个函数接受 两参数, 并按特定规则返回1, 0, -1就可以. — 很方便吧? 但 会大大减慢运行速度. 下面的方法, 俺举例子来说明可能更容易 明白.

比方说你的数列是 l = ['az', 'by'], 你想以第二个字母来排序. 先取出你的关键词, 并与每个字串组成一个元组: new = map (lambda s: (s[1], s), l )

于是new变成[('z', 'az'), ('y', 'by')], 再把new排一下序: new.sort()

则new就变成 [('y', 'by'), ('z', 'az')], 再返回每个元组中 的第二个字串: sorted = map (lambda t: t[1], new)

于是sorted 就是: ['by', 'az']了. 这里的lambda与map用得很 好.

Python2.4以后, sort和sorted的使用可以参考这片 Wiki: HowToSort

1.1.4. 循环
比如for循环. 当循环体很简单时, 则循环的调用前头(overhead) 会显得很臃肿, 此时map又可以帮忙了. 比如你想把一个长数列 l=['a', 'b', ...]中的每个字串变成大写, 可能会用:

Toggle line numbers
   1 import string
   2 newL = []
   3 for s in l: newL.append( string.upper(s) )
用map就可以省去for循环的前头:

Toggle line numbers
   1 import string
   2 newL = map (string.upper, l)
Guido的文章讲得很详细.

1.1.5. 局域变量 及 ‘.’
象上面, 若用 append = newL.append, 及换种import方法:

Toggle line numbers
   1 import string
   2 append = newL.append
   3 for s in l: append (string.upper(s))
会比在for中运行newL.append快一些, 为啥? 局域变量容易寻找.

俺自己就不比较时间了, Skip Montanaro的结果是:

基本循环: 3.47秒
去点用局域变量: 1.79秒
使用map: 0.54秒

1.1.6. try的使用
比如你想计算一个字串数列: l = ['I', 'You', 'Python', 'Perl', ...] 中每个词出现的次数, 你可能会:

Toggle line numbers
   1 count = {}
   2 for s in l:
   3     if not count.has_key(s): count[s] = 0
   4     else: count[s] += 1
由于每次都得在count中寻找是否已有同名关键词, 会很费时间. 而用try:

Toggle line numbers
   1 count ={}
   2 for s in l:
   3     try: count[s] += 1
   4     except KeyError: count[s] = 0
就好得多. 当然若经常出现例外时, 就不要用try了.

1.1.7. import语句
这好理解. 就是避免在函数定义中来import一个模块, 应全在 全局块中来import

1.1.8. 大量数据处理
由于Python中的函数调用前头(overhead)比较重, 所以处理大量 数据时, 应:

Toggle line numbers
   1 def f():
   2 for d in hugeData: …
   3 f()
而不要:

Toggle line numbers
   1 def f(d): …
   2 for d in hugeData: f(d)
这点好象对其它语言也适用, 差不多是放之四海而皆准, 不过对 解释性语言就更重要了.

1.1.9. 减少周期性检查
这是Python的本征功能: 周期性检查有没有其它绪(thread)或系 统信号(signal)等要处理.

可以用sys模块中的setcheckinterval 来设置每次检查的时间间隔.

缺省是10, 即每10个虚拟指令 (virtual instruction)检查一次.

当你不用绪并且也懒得搭理 系统信号时, 将检查周期设长会增加速度, 有时还会很显著.

—编/译完毕. 看来Python是易学难精了, 象围棋?

2. 我们自个儿的体悟
请有心得者分享!

在“大量数据处理”小节里,是不是说,不要再循环体内部调用函数,应该把函数放到外面?从Python2.2开始,”找出速度瓶颈”,已经可以使用hotshot模块了.据说对程序运行效率的影响要比profile小. — jacobfan
“由于Python中的函数调用前头(overhead)比较重, 所以处理大量 数据时, 应: ” 这句译文中,overhead翻译成”前头”好象不妥.翻译成”由于Python中函数调用的开销比较大,…”要好些 — jacobfan
数组排序中讲的方法真的会快点吗? 真的快到我们值得放弃直接用sort得到得可读性吗?值得怀疑 — hoxide
Python2.4以后 sort和sorted的使用更加灵活,link已经加到文中,我没有比较过效率。-yichun
关于 “try的使用”:
其实setdefault方法就是为这个目的设的:

Toggle line numbers
   1 count = {}
   2 for s in l:
   3     count.setdefault(s, 0) += 1
这个其实能做更多。通常遇到的问题是要把类似的东西group起来,所以你可能想用:

Toggle line numbers
   1 count = {}
   2 for s in l:
   3     count.setdefault(s, []).append(s)
但是这样你只能把同样的东西hash起来,而不是一类东西。比如说你有一个dict构成的list叫sequence,需要按这些dict的某个key value分类,你还要对分类后的每个类别里面的这些dict各作一定的操作,你就需要用到Raymond实现的这个groupby,你就可以写:

totals = dict((key, group)
                  for key, group in groupby(sequence, lambda x: x.get(’Age’)))



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值