# 程序运行慢？你怕是写的假 Python

Python程序运行太慢的一个可能的原因是没有尽可能的调用内置方法，下面通过5个例子来演示如何用内置方法提升Python程序的性能。

1. 数组求平方和

```arr = list(range(10000))
```

1.1 最常规的写法

while循环遍历列表求平方和。平均运行时间2.97毫秒。

```def sum_sqr_0(arr):
res = 0
n = len(arr)
i = 0
while i < n:
res += arr[i] ** 2
i += 1
return res
%timeit sum_sqr_0(arr)
2.97 ms ± 36.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
```

1.2 for range代替while循环

```def sum_sqr_1(arr):
res = 0
for i in range(len(arr)):
res += arr[i] ** 2
return res
%timeit sum_sqr_1(arr)
2.9 ms ± 137 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
```

1.3 `for x in arr`代替`for range`

```def sum_sqr_2(arr):
res = 0
for x in arr:
res += x ** 2
return res
%timeit sum_sqr_2(arr)
2.59 ms ± 89 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
```

1.4 sum函数套用map函数

```def sum_sqr_3(arr):
return sum(map(lambda x: x**2, arr))
%timeit sum_sqr_3(arr)
2.36 ms ± 15.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
```

1.5 sum函数套用生成器表达式

```def sum_sqr_4(arr):
return sum(x ** 2 for x in arr)
%timeit sum_sqr_4(arr)
2.35 ms ± 107 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
```

1. 6 sum函数套用列表推导式

```def sum_sqr_5(arr):
return sum([x ** 2 for x in arr])
%timeit sum_sqr_5(arr)
2.06 ms ± 27.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
```

2. 字符串拼接

```from random import randint

def random_letter():
return chr(ord('a') + randint(0, 25))

def random_letters(n):
return "".join([random_letter() for _ in range(n)])

strings = [random_letters(randint(1, 10)) for _ in range(10000)]
```

2.1 最常规的写法

while循环遍历列表，对字符串进行拼接。平均运行时间1.86毫秒。

```def concat_strings_0(strings):
res = ""
n = len(strings)
i = 0
while i < n:
res += strings[i][:3]
i += 1
return res
%timeit concat_strings_0(strings)
1.86 ms ± 74.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
```

2.2 `for range`代替while循环

```def concat_strings_1(strings):
res = ""
for i in range(len(strings)):
res += strings[i][:3]
return res
%timeit concat_strings_1(strings)
1.55 ms ± 32.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
```

2.3 `for x in strings`代替`for range`

```def concat_strings_2(strings):
res = ""
for x in strings:
res += x[:3]
return res
%timeit concat_strings_2(strings)
1.32 ms ± 19.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
```

2.4 .`join`方法套用生成器表达式

```def concat_strings_3(strings):
return "".join(x[:3] for x in strings)
%timeit concat_strings_3(strings)
1.06 ms ± 15.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
```

2.5 .`join`方法套用列表解析式

```def concat_strings_4(strings):
return "".join([x[:3] for x in strings])
%timeit concat_strings_4(strings)
858 µs ± 14.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
```

3. 筛选奇数

```arr = list(range(10000))
```

3.1 最常规的写法

```def filter_odd_0(arr):
res = []
i = 0
n = len(arr)
while i < n:
if arr[i] % 2:
res.append(arr[i])
i += 1
return res
%timeit filter_odd_0(arr)
1.03 ms ± 34.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
```

3.2 `for range`代替while循环

```def filter_odd_1(arr):
res = []
for i in range(len(arr)):
if arr[i] % 2:
res.append(arr[i])
i += 1
return res
%timeit filter_odd_1(arr)
965 µs ± 4.02 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
```

3.3 `for x in arr`代替`for range`

```def filter_odd_2(arr):
res = []
for x in arr:
if x % 2:
res.append(x)
return res
%timeit filter_odd_2(arr)
430 µs ± 9.25 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
```

3.4 list套用filter函数

```def filter_odd_3(arr):
return list(filter(lambda x: x % 2, arr))
%timeit filter_odd_3(arr)
763 µs ± 15.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
```

3.5 list套用生成器表达式

```def filter_odd_4(arr):
return list((x for x in arr if x % 2))
%timeit filter_odd_4(arr)
398 µs ± 16.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
```

3.6 带条件的列表推导式

```def filter_odd_5(arr):
return [x for x in arr if x % 2]
%timeit filter_odd_5(arr)
290 µs ± 5.54 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
```

4. 两个数组相加

```arr1 = list(range(10000))
arr2 = list(range(10000))
```

4.1 最常规的写法

```def arr_sum_0(arr1, arr2):
i = 0
n = len(arr1)
res = []
while i < n:
res.append(arr1[i] + arr2[i])
i += 1
return res
%timeit arr_sum_0(arr1, arr2)
1.23 ms ± 3.77 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
```

4.2 `for range`代替while循环

```def arr_sum_1(arr1, arr2):
res = []
for i in range(len(arr1)):
res.append(arr1[i] + arr2[i])
return res
%timeit arr_sum_1(arr1, arr2)
997 µs ± 7.42 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
```

4.3 `for i, x in enumerate`代替`for range`

```def arr_sum_2(arr1, arr2):
res = arr1.copy()
for i, x in enumerate(arr2):
res[i] += x
return res
%timeit arr_sum_2(arr1, arr2)
799 µs ± 16.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
```

4.4 `for x, y in zip`代替`for range`

```def arr_sum_3(arr1, arr2):
res = []
for x, y in zip(arr1, arr2):
res.append(x + y)
return res
%timeit arr_sum_3(arr1, arr2)
769 µs ± 12.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
```

4.5 列表推导式套用zip

```def arr_sum_4(arr1, arr2):
return [x + y for x, y in zip(arr1, arr2)]
%timeit arr_sum_4(arr1, arr2)
462 µs ± 3.43 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
```

5. 两个列表相同元素的数量

```from random import shuffle
arr1 = list(range(2000))
shuffle(arr1)
arr2 = list(range(1000, 3000))
shuffle(arr2)
```

5.1 最常规的写法

while循环嵌套，判断元素`arr1[i]`是否等于`arr2[j]`，平均运行时间338毫秒。

```def n_common_0(arr1, arr2):
res = 0
i = 0
m = len(arr1)
n = len(arr2)
while i < m:
j = 0
while j < n:
if arr1[i] == arr2[j]:
res += 1
j += 1
i += 1
return res
%timeit n_common_0(arr1, arr2)
338 ms ± 7.81 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
```

5.2 `for range`代替while循环

```def n_common_1(arr1, arr2):
res = 0
for i in range(len(arr1)):
for j in range(len(arr2)):
if arr1[i] == arr2[j]:
res += 1
return res
%timeit n_common_1(arr1, arr2)
233 ms ± 10.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
```

5.3 `for x in arr`代替`for range`

```def n_common_2(arr1, arr2):
res = 0
for x in arr1:
for y in arr2:
if x == y:
res += 1
return res
%timeit n_common_2(arr1, arr2)
84.8 ms ± 1.38 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
```

5.4 使用`if x in arr2`代替内层循环

```def n_common_3(arr1, arr2):
res = 0
for x in arr1:
if x in arr2:
res += 1
return res
%timeit n_common_3(arr1, arr2)
24.9 ms ± 1.39 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
```

5.4 使用更快的算法

```def n_common_4(arr1, arr2):
arr1.sort()
arr2.sort()
res = i = j = 0
m, n = len(arr1), len(arr2)
while i < m and j < n:
if arr1[i] == arr2[j]:
res += 1
i += 1
j += 1
elif arr1[i] > arr2[j]:
j += 1
else:
i += 1
return res
%timeit n_common_4(arr1, arr2)
329 µs ± 12.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
```

5.5 使用更好的数据结构

```def n_common_5(arr1, arr2):
return len(set(arr1) & set(arr2))
%timeit n_common_5(arr1, arr2)
67.2 µs ± 755 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
```

0 条评论

• ### 程序运行慢？你怕是写的假 Python

Python程序运行太慢的一个可能的原因是没有尽可能的调用内置方法，下面通过5个例子来演示如何用内置方法提升PythGon程序的性能。

• ### 编写python程序和运行.py文件的方

前提：已安装好 Subliume Test 3 且已经添加好python编译系统，已安装好python3.7

• ### Python动态强类型解释型语言原理解析

PYTHON是一门动态解释性的强类型定义语言：编写时无需定义变量类型；运行时变量类型强制固定；无需编译，在解释器环境直接运行。

• ### 0基础学Python，1个月写爬虫，走了哪些弯路？

今天我们来分享一位小伙伴的自学之路。当然，如果你没有任何编程基础，也将会和他一样走很多弯路，如果有条件希望你能够找到老师带领。

• ### Python工程师进阶之道

上次在群里有同学又在问基础的问题，我不反感基础问题，就是比较反感不动脑子就贴图出来求解答的问题。有时我干脆不说话，有时我会给个地方让他去搜索。前两天突然冒出个想...

• ### 程序慢的像蜗牛，我该怎么办？

“一猿小讲”公众号的风格就是多元化，偶尔会真情吐露一下程序猿的内心；偶尔也结合自己的经历畅聊一些经验杂谈；其中也不乏幽默风趣的技术故事。分享是件快乐的事情，工作...

• ### test

我的上一篇关于自动化测试的文章，大抵已经在一年以前——《哪个才是最适合你的 Web UI 自动化测试框架》。这么长的时间里，没有相关的文章，总得给自己找一个合适...

• ### 是的，Python是慢，但我不在乎

几年前我做运维时用到 Python，从此便成为 Python 的狂热分子，工作上能用程序自动化实现的，我都尽可能积极的使用 Python，极大的提高了工作效率，...

• ### 520，单身程序员如何假装有女朋友？

每次到了这种节日，总能够感受到浓浓的恶意。最好的方式当然是一天都在家，关闭朋友圈。

• ### 对比java和python

对比java和python  　　1.难易度而言。python远远简单于java。 　　2.开发速度。Python远优于java 　　3.运行速度。...

• ### Python不是Java (zt)

作者：Phillip J. Eby. 翻译：ShiningRay @ NirvanaStudio 原文地址：[[[url]http://dirtsimple...

• ### 零基础学习 Python 之 for 循环语句

大家好，这里是零基础学习 Python 系列，在这里我将从最基本的Python 写起，然后再慢慢涉及到高阶以及具体应用方面。我是完全自学的 Python，所以很...

• ### pyw格式、命令行运行python程序与

在我学习python的过程中我通常使用IDLE来运行程序，这一步骤太过繁琐（需要打开文件，再按下F5），使我慢慢开始厌烦起来，甚至不想再继续学习下去了，去年有...

• ### 爬取百万github用户数据，查找谁才是python大牛？

在上周写完用scrapy爬去知乎用户信息的爬虫之后，github上star个数一下就在公司小组内部排的上名次了，我还信誓旦旦的跟上级吹牛皮说如果再写一个，都不好...

• ### Python 为什么这么慢？

大家好，我是猫哥。今天分享一篇文章，讨论了拖慢 Python 整体性能的三大原因。在开始正文之前，需要说明一下（免得有人误以为 Python 慢就不值得使用）：...

• ### Day-01 Python基础

Python是一门解释型，弱类型，高级开发编程语言；可广泛应用于众多领域，如：网页开发，数据分析，爬虫等众多领域。

• ### 一个机械生的Python转行自述

在此把这段转行经历发出来，给正在转行之路上努力着的小伙伴，做一个参考，只要你好好努力，工作肯定会有的。

• ### 成为专业程序员的 6 个技巧

成为专业程序员的 6 个技巧 1.在你责怪别人之前，先检查自己的代码 先想一想自己的假设和其他人的假设。来自不同供应商的工具可能内置不同的假设，即便是相同的供应...