本文记录了 Python 编程中各种提速的小技巧,注意只记录小技巧。

 

列表解析 VS 生成器

优先选择 生成器

time.clock()
[i for i in range(10000000)]            # 1.04134576438
(i for i in range(10000000))            # 0.179256006437
print(time.clock())

差了 10 倍

 

list 查找 VS set 查找

优先选择 set 查找

data = (i for i in range(10000000))            # 0.179256006437
list_data = list(data)
set_data = set(data)

time.clock()
1098987 in list_data       # 0.017s 左右
1098987 in set_data         # 3.66553462739e-06
print(time.clock())

差了 10000 倍

在需要查找时,尽量生成 set,如果生成其他的,再转换成 set,这个转换比较耗时,具体可以测试下

 

双 list 查找 VS dict 查找

优先选择 dict 查找

list1 = range(10000000)
list2 = range(10000000)

dict_data = dict(zip(list1, list2))


time.clock()
# list2[list1.index(888888)]      # 0.015s
dict_data[888888]                 # 5.86485540382e-06
print(time.clock())

差了 10000 倍

 

For VS While

优先选择 for 循环

time.clock()

s, i = 0, 0
while i<10000000:        # 1.55s
    i += 1
    s += 1

# s = 0
# for i in range(10000001):   # 1.35s
#     s += 1

print(time.clock())

while 通常需要判断 结束的条件,所以会慢

 

利用缓存机制加速递归函数

仅 python3 支持

普通递归

def fib(n):
    return (1 if n in (1, 2) else fib(n-1) + fib(n-2))

time.clock()
fib(30)                 # 0.33s
print(time.clock())

缓存优化的递归

from functools import lru_cache

@lru_cache(100)
def fib(n):
    return (1 if n in (1, 2) else fib(n-1) + fib(n-2))

time.clock()
fib(30)             # 2.6025295854463614e-05
print(time.clock())

差了 10000 倍

 

使用 numba 加速 python 函数

这个方法比较麻烦,后续我会专门写一篇博客介绍 numba, 这里只举个例子

注意,必须使用 numpy 标准库 作为 numba 加速对象

@jit
def sum2d(arr):
    M, N = arr.shape
    result = 0.0
    for i in range(M):
        for j in range(N):
            result += arr[i,j]
    return result


time.clock()

arr = np.array([range(100000)])
print sum2d(arr)

print(time.clock())

# 带 @jit
# 4999950000.0
# 0.482289656335

# 不带 @jit
# 4999950000.0
# 0.039884608124

差了将近 10 倍

数据量大的计算使用jit才能发挥作用,简单的计算反而会慢

Python和Java一样是基于虚拟机的语言,并不是像C/C++那样将程序代码编译成机器语言再运行,而是解释一行执行一行,速度比较慢。使用Numba库的JIT技术编译以后,可以明显提高程序的运行速度。

 

numpy.func VS math.func

numpy 更适合 批处理数据

# encoding:utf-8
import time
import math
import numpy as np


time.clock()

# for i in range(1, 1000000):
#     # math.log(i)                 # 0.377321537556
#     np.log(i)                   # 1.5135847542      # 逐个操作, numpy 效率更低


np.log(range(1, 1000000))       # 0.124642653573    # 批量处理 才是 numpy 的强项

print(time.clock())

差了 3 倍

 

动态扩容 VS 预分配内存

动态扩容就是事后增加行或者列;预分配内存就是事先定好行和列

# encoding:utf-8
import time
import numpy as np
import pandas as pd


time.clock()

# data = pd.DataFrame(columns=range(26))      # 动态扩容,15s 以上
data = pd.DataFrame(np.zeros((10000, 26)))      # 预分配内存, 2s
for i in range(10000):
    data.loc[i, :] = range(i, i+26)

print(time.clock())

差了 7 倍

 

未完待续...