应该怎么提升Python的程序运行?编制汇总结果 有更好方法吗?

1. Python编程快速记忆

1.1. 最常用的

* 一个最常用的速度陷进坑(至于我还没看到网上介绍就沦陷了好几次

) 是: 很多短字串并成长字串时候, 大家一般会用:

切换行号显示

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次, ... .

那怎么办 ? 我们还可以看看其他人的解答方法

1.1.1. 其实找出速度瓶颈

* 1)第一大家应该先学会怎么去找出速度瓶颈: Python自带些功能有profile

以下模块:

切换行号显示

1 import profile

2 profile.run ('想要检查的函数名()')

接下来会打印出在那个函数里调用了好几次其它的函数, 各占了多少时间, 总共用了多久时间等其他信息

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

1.1.2. 字串相并

* 就上面的例子应该, 用 :

切换行号显示

1 longStr =''.join(shortStrs)

立马就有结果了, :) 但假如shortStrs里面不都是字串, 而包含了其他些数 字 ? 间接用join就会出错了. 没事, 这样的话:

切换行号显示

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', ...]中的每个字串变成大写, 就可能会用到:

切换行号显示:

1 import string

2 newL = []

3 for s in l: newL.append( string.upper(s) )

用map就可以省去for循环的前头:

切换行号显示

1 import string

2 newL = map (string.upper, l)

Guido的文章讲得很详细.

1.1.5. 局域变量 及 '.'

像上面, 若可以用 append = newL.append, 及换种import方法:

切换行号显示

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', ...] 中每个词出现的次数, 你就可能会:

切换行号显示

1 count = {}

2 for s in l:

3 if not count.has_key(s): count[s] = 0

4 else: count[s] += 1

由于每次都得在count中寻找是否就已有同名关键词, 就会很费时间. 如果用try:

切换行号显示

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)比较重, 所以处理大量 数据时, 应:

切换行号显示

1 def f():

2 for d in hugeData: ...

3 f()

不能要:

切换行号显示

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. 我们可以自己体会

请大家可以分享下!

2.1. 来源于

*

P

ython性能调试优越 ~ flydudu 分享

2.2. 思量

* 在“大量数据处理”一小节里,是不是应该说,不要再循环体内部调用函数,可以把函数放到外面?从Python2.2开始,"找出速度瓶颈",已经就可以使用hotshot模块了.据说对程序运行效率的影响要比profile还要小. -- jacobfan

* "由于Python中的函数调用前头(overhead)比较重, 所以处理大量 数据时, 应该: " 这句翻译文中,overhead翻译成"前面"好象有些不妥.翻译成"由于Python中函数调用的开销会比较大,..."要好些多了 -- jacobfan

* 数组排序中讲的方法真的还可以快点的吗? 真的快到觉得应该放弃直接用sort得到的可读性吗?值得怀疑 -- hoxide

* Python2.4以后 sort和sorted的使用会更加灵活,link其实已经加到文中,我没有比较过其他平率。-yichun

* 关于 “try的使用方法”:

其实setdefault方法就是为这个结果而设的:

切换行号显示

1 count = {}

2 for s in l:

3 count.setdefault(s, 0) += 1

这个还可以做很多。通常遇到的问题是要把相似的东西group起来,所以你接下来可以用:

切换行号显示

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')))

- yichun

* shortStrs = [str(s) for s in shortStrs[i]]这句我在python2.5下报错(i未定义),我可以改写成shortStrs = [str(s) for s in shortStrs]就可以啦。

下次分享我简单经常用的Python库,持续更新哦。大家觉得还有哪些方法呢? 可以一一举例。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180127A0O85300?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券