Python 作为一种广泛使用的解释型高级通用编程语言,以其简洁的语法、优雅的代码风格和丰富的第三方库生态而闻名。然而,与 C/C++ 等编译型语言相比,Python 在执行速度上存在天然劣势。这主要源于其动态类型系统和全局解释器锁(GIL)机制。尽管无法改变语言底层特性,但通过合理的编码习惯和算法优化,开发者可以显著提升脚本的运行效率。
为了量化性能差异,我们首先定义一个计时装饰器 ,用于打印指定函数的运行时间:
Python 作为解释型语言存在执行效率瓶颈,通过选择合适的数据结构、利用内置函数、优化循环方式、避免重复计算及控制变量作用域,可显著提升脚本运行速度。详细对比了列表与元组、字符串拼接方法、列表推导式与普通循环的性能差异,并提供了正则表达式预编译及局部变量优化的具体代码示例,旨在帮助开发者编写更高效的 Python 程序。

Python 作为一种广泛使用的解释型高级通用编程语言,以其简洁的语法、优雅的代码风格和丰富的第三方库生态而闻名。然而,与 C/C++ 等编译型语言相比,Python 在执行速度上存在天然劣势。这主要源于其动态类型系统和全局解释器锁(GIL)机制。尽管无法改变语言底层特性,但通过合理的编码习惯和算法优化,开发者可以显著提升脚本的运行效率。
为了量化性能差异,我们首先定义一个计时装饰器 ,用于打印指定函数的运行时间:
timeshowdef timeshow(func):
from time import time
def newfunc(*arg, **kw):
t1 = time()
res = func(*arg, **kw)
t2 = time()
print(f"{func.__name__: >10} : {t2-t1:.6f} sec")
return res
return newfunc
数据结构的选择对 Python 脚本的运行时间有显著影响。Python 内置了四种主要数据结构:列表(List)、元组(Tuple)、集合(Set)和字典(Dictionary)。许多开发者习惯在所有场景下使用列表,但这往往不是最优解。
列表 vs 元组 元组是不可变对象,而列表是可变的。在内存分配和访问机制上,元组通常比列表更高效。由于元组创建后不可修改,解释器在存储时可以进行更多优化。
通过 dis 模块反汇编字节码,我们可以直观看到两者的区别:
import dis
def a():
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
x = data[5]
return x
def b():
data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
x = data[5]
return x
print("-----:使用列表的机器码:------")
dis.dis(a)
print("-----:使用元组的机器码:------")
dis.dis(b)
运行结果显示,构建列表需要逐个加载常量并执行 BUILD_LIST 指令,而构建元组只需一次性加载常量元组并执行 STORE_FAST。这意味着在只读数据场景下,优先使用元组能减少字节码指令数量,提升检索速度。
Python 拥有大量经过 C 语言优化的内置函数和标准库。如果手动编写基础逻辑(如字符串拼接、数学运算),不仅代码冗长,且运行效率远低于内置实现。
字符串拼接示例
在循环中频繁使用 += 拼接字符串会导致创建大量临时字符串对象,消耗额外内存和时间。推荐使用 join() 方法。
@timeshow
def f1(list_data):
s = ""
for substring in list_data:
s += substring
return s
@timeshow
def f2(list_data):
s = "".join(list_data)
return s
l = ["I", "Love", "Python"] * 1000
f1(l)
f2(l)
测试表明,join() 方法的执行时间通常仅为普通循环拼接的几分之一。这是因为 join() 会预先计算所需内存空间,一次性完成分配,避免了多次内存重分配。
Python 中的 for 循环在解释层执行,开销较大。利用列表推导式、生成器表达式或内置高阶函数(如 filter, map)可以将部分逻辑下沉到 C 层执行,从而加速。
获取能被 7 整除的数字
# ❌ 普通循环
@timeshow
def f_loop(n):
L = []
for i in range(n):
if i % 7 == 0:
L.append(i)
return L
# ✅ 列表推导式
@timeshow
def f_list(n):
L = [i for i in range(n) if i % 7 == 0]
return L
# ✅ 迭代器
@timeshow
def f_iter(n):
L = (i for i in range(n) if i % 7 == 0)
return L
# ✅ 过滤器
@timeshow
def f_filter(n):
L = filter(lambda x: x % 7 == 0, range(n))
return L
# ✅ 精确控制循环次数
@timeshow
def f_mind(n):
L = (i*7 for i in range(n//7))
return L
n = 1_000_000
f_loop(n)
f_list(n)
f_iter(n)
f_filter(n)
f_mind(n)
实验数据显示,列表推导式比普通循环快约 30%,而生成器和过滤器在处理大数据集时优势更为明显,因为它们实现了惰性求值,无需一次性加载所有结果到内存。
在循环内部进行耗时操作(如正则匹配、文件 IO、网络请求)是常见的性能陷阱。应将可复用的计算结果提取到循环外部。
正则表达式预编译
每次调用 re.search 都会重新解析模式字符串。正确的做法是使用 re.compile 预编译正则对象。
# ❌ 应避免的方式
@timeshow
def f_more(s):
import re
for i in s:
m = re.search(r'a*[a-z]?c', i)
# ✅ 更好的方式
@timeshow
def f_less(s):
import re
regex = re.compile(r'a*[a-z]?c')
for i in s:
m = regex.search(i)
s = ["abctestabc"] * 1_000
f_more(s)
f_less(s)
预编译正则对象将解析过程移至循环外,仅保留匹配过程,大幅减少了 CPU 周期消耗。
Python 访问局部变量的速度远快于全局变量。这是因为全局变量查找涉及作用域链遍历(LEGB 规则),而局部变量直接通过栈帧索引访问。
局部变量优化
# ❌ 应该避免的方式:全局变量
message = "Line1\n"
message += "Line2\n"
message += "Line3\n"
x = 5
y = 6
def add_global():
return x + y
# ✅ 更好的方式:局部变量
l = ["Line1", "Line2", "Line3"]
message = '\n'.join(l)
def add_local():
x = 5
y = 6
return x + y
此外,应尽量减少不必要的对象创建。例如,使用列表推导式替代 append 循环,或使用生成器替代大列表,以降低内存峰值,减少垃圾回收(GC)压力。
在进行优化前,准确的性能分析至关重要。Python 提供了多种工具来定位瓶颈:
示例:
import timeit
timeit.timeit('sum(range(1000))', number=10000)
优化 Python 代码性能并非一蹴而就,而是需要结合具体场景选择合适的策略。核心原则包括:优先使用内置函数、减少循环开销、预编译重复资源、以及合理管理变量作用域。通过上述技巧,开发者可以在不改变语言特性的前提下,显著提升程序运行效率,降低资源消耗。在实际开发中,建议先通过性能分析工具定位瓶颈,再进行针对性优化,避免过早优化带来的维护成本增加。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online