加速 Python 循环的 12 种方法,最高提速 900 倍

chatgpt赋能python:如何加速Python中的for循环操作? 本文由chatgpt生成,文章没有在chatgpt生成的基础上进行任何的修改。以上只是chatgpt能力的冰山一角。作为通用的Aigc大模型,只是展现它原本的实力。对于颠覆工作方式的ChatGPT,应该选择拥抱而不是抗拒,未来属于“会用”AI的人。🧡AI职场汇报智能办公文案写作效率提升教程 🧡专注于AI+职场+办公方向。下图是课程的整体大纲下图是AI职场汇报智能办公文案写作效率提升教程中用到的ai工具。 阅读详情

你好,我是坚持分享干货的 EarlGrey,翻译出版过《Python编程无师自通》、《Python并行计算手册》等技术书籍。

如果我的分享对你有帮助,请关注我,一起向上进击。

作者:Nirmalya Ghosh

来源:deephub

转自:数据STUDIO

免费送一本推荐算法书(点此查看详情)

在本文中,我将介绍一些简单的方法,可以将Python for循环的速度提高1.3到900倍。

Python内建的一个常用功能是timeit模块。下面几节中我们将使用它来度量循环的当前性能和改进后的性能。

对于每种方法,我们通过运行测试来建立基线,该测试包括在10次测试运行中运行被测函数100K次(循环),然后计算每个循环的平均时间(以纳秒为单位,ns)。

f33763916d1eb431001730c181b29672.png

几个简单方法

1、列表推导式

# Baseline version (Inefficient way)
 # Calculating the power of numbers
 # Without using List Comprehension
 def test_01_v0(numbers):
   output = []
   for n in numbers:
       output.append(n ** 2.5)
   return output
 
 # Improved version
 # (Using List Comprehension)
 def test_01_v1(numbers):
   output = [n ** 2.5 for n in numbers]
   return output

结果如下:

# Summary Of Test Results
      Baseline: 32.158 ns per loop
      Improved: 16.040 ns per loop
 % Improvement: 50.1 %
      Speedup: 2.00x

可以看到使用列表推导式可以得到2倍速的提高

2、在外部计算长度

如果需要依靠列表的长度进行迭代,请在for循环之外进行计算。

# Baseline version (Inefficient way)
 # (Length calculation inside for loop)
 def test_02_v0(numbers):
   output_list = []
   for i in range(len(numbers)):
     output_list.append(i * 2)
   return output_list
 
 # Improved version
 # (Length calculation outside for loop)
 def test_02_v1(numbers):
   my_list_length = len(numbers)
   output_list = []
   for i in range(my_list_length):
     output_list.append(i * 2)
   return output_list

通过将列表长度计算移出for循环,加速1.6倍,这个方法可能很少有人知道吧。

# Summary Of Test Results
      Baseline: 112.135 ns per loop
      Improved: 68.304 ns per loop
 % Improvement: 39.1 %
      Speedup: 1.64x

3、使用Set

在使用for循环进行比较的情况下使用set。

# Use for loops for nested lookups
 def test_03_v0(list_1, list_2):
   # Baseline version (Inefficient way)
   # (nested lookups using for loop)
   common_items = []
   for item in list_1:
       if item in list_2:
           common_items.append(item)
   return common_items
 
 def test_03_v1(list_1, list_2):
   # Improved version
   # (sets to replace nested lookups)
   s_1 = set(list_1)
   s_2 = set(list_2)
   output_list = []
   common_items = s_1.intersection(s_2)
   return common_items

在使用嵌套for循环进行比较的情况下,使用set加速498x

# Summary Of Test Results
      Baseline: 9047.078 ns per loop
      Improved:   18.161 ns per loop
 % Improvement: 99.8 %
      Speedup: 498.17x

4、跳过不相关的迭代

避免冗余计算,即跳过不相关的迭代。

# Example of inefficient code used to find
 # the first even square in a list of numbers
 def function_do_something(numbers):
   for n in numbers:
     square = n * n
     if square % 2 == 0:
         return square
 
   return None  # No even square found
 
 # Example of improved code that
 # finds result without redundant computations
 def function_do_something_v1(numbers):
   even_numbers = [i for n in numbers if n%2==0]
   for n in even_numbers:
     square = n * n
     return square
 
   return None  # No even square found

这个方法要在设计for循环内容的时候进行代码设计,具体能提升多少可能根据实际情况不同:

# Summary Of Test Results
      Baseline: 16.912 ns per loop
      Improved: 8.697 ns per loop
 % Improvement: 48.6 %
      Speedup: 1.94x

5、代码合并

在某些情况下,直接将简单函数的代码合并到循环中可以提高代码的紧凑性和执行速度。

# Example of inefficient code
 # Loop that calls the is_prime function n times.
 def is_prime(n):
   if n <= 1:
     return False
   for i in range(2, int(n**0.5) + 1):
     if n % i == 0:
       return False
 
   return True
 
 def test_05_v0(n):
   # Baseline version (Inefficient way)
   # (calls the is_prime function n times)
   count = 0
   for i in range(2, n + 1):
     if is_prime(i):
       count += 1
   return count
 
 def test_05_v1(n):
   # Improved version
   # (inlines the logic of the is_prime function)
   count = 0
   for i in range(2, n + 1):
     if i <= 1:
       continue
     for j in range(2, int(i**0.5) + 1):
       if i % j == 0:
         break
     else:
       count += 1
   return count

这样也可以提高1.3倍

# Summary Of Test Results
      Baseline: 1271.188 ns per loop
      Improved: 939.603 ns per loop
 % Improvement: 26.1 %
      Speedup: 1.35x

这是为什么呢?

调用函数涉及开销,例如在堆栈上推入和弹出变量、函数查找和参数传递。当一个简单的函数在循环中被重复调用时,函数调用的开销会增加并影响性能。所以将函数的代码直接内联到循环中可以消除这种开销,从而可能显著提高速度。

⚠️但是这里需要注意,平衡代码可读性和函数调用的频率是一个要考虑的问题。

一些小技巧

6 .避免重复

考虑避免重复计算,其中一些计算可能是多余的,并且会减慢代码的速度。相反,在适用的情况下考虑预计算。

def test_07_v0(n):
   # Example of inefficient code
   # Repetitive calculation within nested loop
   result = 0
   for i in range(n):
     for j in range(n):
       result += i * j
   return result
 
 def test_07_v1(n):
   # Example of improved code
   # Utilize precomputed values to help speedup
   pv = [[i * j for j in range(n)] for i in range(n)]
   result = 0
   for i in range(n):
     result += sum(pv[i][:i+1])
   return result

结果如下

# Summary Of Test Results
      Baseline: 139.146 ns per loop
      Improved: 92.325 ns per loop
 % Improvement: 33.6 %
      Speedup: 1.51x

7、使用Generators

生成器支持延迟求值,也就是说,只有当你向它请求下一个值时,里面的表达式才会被求值,动态处理数据有助于减少内存使用并提高性能。尤其是大型数据集中

def test_08_v0(n):
   # Baseline version (Inefficient way)
   # (Inefficiently calculates the nth Fibonacci
   # number using a list)
   if n <= 1:
     return n
   f_list = [0, 1]
   for i in range(2, n + 1):
     f_list.append(f_list[i - 1] + f_list[i - 2])
   return f_list[n]
 
 def test_08_v1(n):
   # Improved version
   # (Efficiently calculates the nth Fibonacci
   # number using a generator)
   a, b = 0, 1
   for _ in range(n):
     yield a
     a, b = b, a + b

可以看到提升很明显:

# Summary Of Test Results
      Baseline: 0.083 ns per loop
      Improved: 0.004 ns per loop
 % Improvement: 95.5 %
      Speedup: 22.06x

8、map()函数

使用Python内置的map()函数。它允许在不使用显式for循环的情况下处理和转换可迭代对象中的所有项。

def some_function_X(x):
   # This would normally be a function containing application logic
   # which required it to be made into a separate function
   # (for the purpose of this test, just calculate and return the square)
   return x**2
 
 def test_09_v0(numbers):
   # Baseline version (Inefficient way)
   output = []
   for i in numbers:
     output.append(some_function_X(i))
 
   return output
 
 def test_09_v1(numbers):
   # Improved version
   # (Using Python's built-in map() function)
   output = map(some_function_X, numbers)
   return output

使用Python内置的map()函数代替显式的for循环加速了970x。

# Summary Of Test Results
      Baseline: 4.402 ns per loop
      Improved: 0.005 ns per loop
 % Improvement: 99.9 %
      Speedup: 970.69x

这是为什么呢?

map()函数是用C语言编写的,并且经过了高度优化,因此它的内部隐含循环比常规的Python for循环要高效得多。因此速度加快了,或者可以说Python还是太慢,哈。

9、使用Memoization

记忆优化算法的思想是缓存(或“记忆”)昂贵的函数调用的结果,并在出现相同的输入时返回它们。它可以减少冗余计算,加快程序速度。

首先是低效的版本。

# Example of inefficient code
 def fibonacci(n):
   if n == 0:
     return 0
   elif n == 1:
     return 1
   return fibonacci(n - 1) + fibonacci(n-2)
 
 def test_10_v0(list_of_numbers):
   output = []
   for i in numbers:
     output.append(fibonacci(i))
 
   return output

然后我们使用Python的内置functools的lru_cache函数。

# Example of efficient code
 # Using Python's functools' lru_cache function
 import functools
 
 @functools.lru_cache()
 def fibonacci_v2(n):
   if n == 0:
     return 0
   elif n == 1:
     return 1
   return fibonacci_v2(n - 1) + fibonacci_v2(n-2)
 
 def _test_10_v1(numbers):
   output = []
   for i in numbers:
     output.append(fibonacci_v2(i))
 
   return output

结果如下:

# Summary Of Test Results
      Baseline: 63.664 ns per loop
      Improved: 1.104 ns per loop
 % Improvement: 98.3 %
      Speedup: 57.69x

使用Python的内置functools的lru_cache函数使用Memoization加速57x。

lru_cache函数是如何实现的?

“LRU”是“Least Recently Used”的缩写。lru_cache是一个装饰器,可以应用于函数以启用memoization。它将最近函数调用的结果存储在缓存中,当再次出现相同的输入时,可以提供缓存的结果,从而节省了计算时间。lru_cache函数,当作为装饰器应用时,允许一个可选的maxsize参数,maxsize参数决定了缓存的最大大小(即,它为多少个不同的输入值存储结果)。如果maxsize参数设置为None,则禁用LRU特性,缓存可以不受约束地增长,这会消耗很多的内存。这是最简单的空间换时间的优化方法。

10、向量化

import numpy as np
 
 def test_11_v0(n):
   # Baseline version
   # (Inefficient way of summing numbers in a range)
   output = 0
   for i in range(0, n):
     output = output + i
 
   return output
 
 def test_11_v1(n):
   # Improved version
   # (# Efficient way of summing numbers in a range)
   output = np.sum(np.arange(n))
   return output

向量化一般用于机器学习的数据处理库numpy和pandas

# Summary Of Test Results
      Baseline: 32.936 ns per loop
      Improved: 1.171 ns per loop
 % Improvement: 96.4 %
      Speedup: 28.13x

11、避免创建中间列表

使用filterfalse可以避免创建中间列表。它有助于使用更少的内存。

def test_12_v0(numbers):
   # Baseline version (Inefficient way)
   filtered_data = []
   for i in numbers:
     filtered_data.extend(list(
         filter(lambda x: x % 5 == 0,
                 range(1, i**2))))
   
   return filtered_data

使用Python的内置itertools的filterfalse函数实现相同功能的改进版本。

from itertools import filterfalse
 
 def test_12_v1(numbers):
   # Improved version
   # (using filterfalse)
   filtered_data = []
   for i in numbers:
     filtered_data.extend(list(
         filterfalse(lambda x: x % 5 != 0,
                     range(1, i**2))))
     
     return filtered_data

这个方法根据用例的不同,执行速度可能没有显著提高,但通过避免创建中间列表可以降低内存使用。我们这里获得了131倍的提高

# Summary Of Test Results
      Baseline: 333167.790 ns per loop
      Improved: 2541.850 ns per loop
 % Improvement: 99.2 %
      Speedup: 131.07x

12、高效连接字符串

任何使用+操作符的字符串连接操作都会很慢,并且会消耗更多内存。使用join代替。

def test_13_v0(l_strings):
   # Baseline version (Inefficient way)
   # (concatenation using the += operator)
   output = ""
   for a_str in l_strings:
     output += a_str
 
   return output
 
 def test_13_v1(numbers):
   # Improved version
   # (using join)
   output_list = []
   for a_str in l_strings:
     output_list.append(a_str)
 
   return "".join(output_list)

该测试需要一种简单的方法来生成一个较大的字符串列表,所以写了一个简单的辅助函数来生成运行测试所需的字符串列表。

from faker import Faker
 
 def generate_fake_names(count : int=10000):
   # Helper function used to generate a
   # large-ish list of names
   fake = Faker()
   output_list = []
   for _ in range(count):
     output_list.append(fake.name())
 
   return output_list
 
 l_strings = generate_fake_names(count=50000)

结果如下:

# Summary Of Test Results
      Baseline: 32.423 ns per loop
      Improved: 21.051 ns per loop
 % Improvement: 35.1 %
      Speedup: 1.54x

使用连接函数而不是使用+运算符加速1.5倍。为什么连接函数更快?

使用+操作符的字符串连接操作的时间复杂度为O(n²),而使用join函数的字符串连接操作的时间复杂度为O(n)。

总结

本文介绍了一些简单的方法,将Python for循环的提升了1.3到970x。

  • 使用Python内置的map()函数代替显式的for循环加速970x

  • 使用set代替嵌套的for循环加速498x[技巧#3]

  • 使用itertools的filterfalse函数加速131x

  • 使用lru_cache函数使用Memoization加速57x

- EOF -

文章已经看到这了,别忘了在右下角点个“赞”和“在看”鼓励哦~

推荐阅读  点击标题可跳转

1、Python 项目工程化最佳实践

2、Python 可以比 C 还要快!

3、streamlit,一个超强的 Python 库

4、豆瓣8.9分的C++经典之作,免费送!

5、Python 3.12 版本有什么变化?

回复下方「关键词」,获取优质资源

回复关键词「 pybook03」,领取进击的Grey与小伙伴一起翻译的《Think Python 2e》电子版

回复关键词「书单02」,领取进击的Grey整理的 10 本 Python 入门书的电子版

👇关注我的公众号👇

告诉你更多细节干货

6d9d0c9a6f9abbac6154e841a5f06518.jpeg

欢迎围观我的朋友圈

👆每天更新所想所悟

优化 Python 中的循环:提高效率的技巧与实例 通过应用上述优化技巧,可以显著提高 Python 程序中循环的执行效率。然而,优化循环并不是万能的,有时候程序的其他部分可能成为性能瓶颈。因此,在进行优化时,需要结合具体情况进行综合考虑,全面提升程序的整体性能。循环是编程中常用的控制结构,用于重复执行一段代码。在 Python 中,循环的效率对于处理大型数据集或者需要频繁执行的任务至关重要。本文将介绍一些优化循环的技巧和实例,以提高 Python 程序的执行效率。优化 Python 中的循环:提高效率的技巧与实例。 阅读详情

相关推荐

ROS2 -Jazzy 一步一步(第一步_工作空间以及编译)

文件夹作用特点是否需要手动创建/维护src存放自己写的 ROS 2 包一个 workspace 可以有多个包需要手动创建build保存编译过程中的中间文件每个包生成对应子目录自动生成,可删除install保存编译完成后的功能包每个包有独立子目录,含可执行文件自动生成,可删除log保存编译日志用于查看错误原因、调试自动生成,不需修改colcon是 ROS 2 推荐使用的构建工具自动处理功能包的依赖和编译顺序一条命令就能编译整个工作空间。

jerrykorea的博客 1380

加速Python循环的12种方法,最高可以提速900倍

本文介绍了一些简单的方法,将Python for循环的提升了1.3到970x。使用Python内置的map()函数代替显式的for循环加速970x使用set代替嵌套的for循环加速498x[技巧#3]使用itertools的filterfalse函数加速131x使用lru_cache函数使用Memoization加速57x作者:Nirmalya Ghosh。

deephub 5305

单片机课程设计——交通灯

单片机课程设计——交通灯一、课程设计主要内容1.1 题目1.2摘要1.3关键词二、设计要求三、设计方案四、参考电路设计4.1.1数码管的设计4.1.2对应程序4.2.1独立按键的设计4.2.2对应程序4.2.3 使用逻辑4.3.1LED模块的设置4.3.2 LED实物图4.3.3 LED显示程序五、调试要点5.1 单片机最小系统5.2 数码管模块5.3 LED模块5.4 独立按键六、总结七、成品图完整程序 一、课程设计主要内容 1.1 题目 交通灯设计 1.2摘要 近年来,随着我国国民经济的快速发展,我国机

PKPROTEUS的博客 3万+

Python加速循环的若干个办法

Python加速循环的若干个办法: (1)使用Python封装的函数,而不是自编函数; (2)使用Numpy函数,因为Numpy底层代码语言是C++; 上面两个效果仍不好,尝试下面方法中的一种或多种: (3)将需要处理的图像分为若干个部分,使用multiprocessing多进程并行化,充分利用CPU; (4)采用numba(@njit)加速循环部分(但是与multiprocessing似乎不兼容); (5)采用Cython,修改少量代码,...

qq_39654162的博客 3194

Yersinia:layer 2攻击框架!全参数详细教程!Kali Linux教程!

Yersinia是一个专为执行二层网络攻击设计的框架,利用多种网络协议的弱点进行渗透测试和网络分析。它支持针对生成树协议(STP)、思科发现协议(CDP)、动态中继协议(DTP)、动态主机配置协议(DHCP)、热备用路由器协议(HSRP)、802.1q、802.1x、交换机间链路协议(ISL)和VLAN中继协议(VTP)的攻击。这些攻击可能导致网络中的拒绝服务(DoS)或为更复杂的攻击创造条件。Yersinia对渗透测试人员和网络管理员非常有用,但使用时需谨慎,以免造成网络不稳定。

qq_24305079的博客 2281

基于Simulink的双PMSM差速驱动转矩同步控制建模示例

本文详细介绍了基于Simulink的双永磁同步电机(PMSM)差速驱动转矩同步控制建模方法。针对AGV/叉车等双电机独立驱动系统的转矩不同步问题,提出主从式+交叉耦合控制策略,在Simulink中实现直线行驶、90°转弯和单轮打滑恢复三种工况的仿真验证。通过动力学建模、参数差异设置、同步误差定义及控制律设计,最终实现同步误差<3%、转弯半径跟踪误差<5%、打滑后100ms内恢复的性能指标。文章特别强调了实际工程中的参数标定、通信同步和故障处理要点,并提供了完整的Simulink建模步骤和工具箱使

xiaoheshang_123的博客 206

如何提高python的for循环效率

提高 Python for 循环的效率的方法有以下几种: 利用内置函数:使用内置函数可以加速代码的执行,例如 map() 和 filter()。 避免不必要的循环:如果可以直接使用列表推导式或生成器表达式代替 for 循环,则应该使用它们。 利用预先计算:如果可以预先计算某些值,则应该尽量预先计算。 减少循环次数:应该尽量减少循环的次数,例如,使用 while 循环代替 for 循环。 ...

weixin_42596246的博客 4719

高通GAIA V3命令参考手册的研读学习(15):自定制命令的详细工作描述

里的示例一样,手机APP发出这个GetManuFacturer的命令发0x0000,那么耳机回复:0x8000, 同时在回复的playload部分,用最多15个字节的ACSII码来表达制造商信息(因此最多15个字母)。那么这个APP在通过GAIA协议控制这个耳机时,不仅可以通过前面讲过的vendor ID来识别,也可以更进一步通过这个命令来识别这个耳机,到底是不是本公司的。通过这个可变长度的playload,真的是可以传达极多的事先约定的信息,相当的灵活,真是不错!这个命令用来得到设备的制造商信息。

qq_37191547的博客 399

加速Python循环的12种方法,最高可以提速900倍!

在本文中,我将介绍一些简单的方法,可以将Python for循环的速度提高1.3到900倍

m0_75067840的博客 868

国科大作业考试资料《人工智能原理与算法》2024新编-第二次作业整理

1、对于下列活动,分别给出任务环境的PEAS描述, 并按2.3.2节列出的性质进行分析: 3、为图2.2中描述的吸尘器世界实现一个可以进行性能度量的环境模拟器。你的实现是必须是模块化的,以使传感器、执行器和环境特征(大小、形状、灰尘放置等)便于修改。 4、实现上述题目真空吸尘器环境中的简单反射Agent。用所有可能的初始灰尘分布和Agent位置,运行环境模拟器和Agent。记录Agent在每种情况下的性能评分和总体平均评分。

MatsumotoChrikk 1187

华为OD机试双机位B卷 - 比赛的冠亚季军 (C++ & Python & JAVA & JS & GO)

华为OD机试双机位B卷 比赛的冠亚季军,提供Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解。 华为OD机试 比赛的冠亚季军

qq_45776114的博客 703

【Python】加速Python循环的12种方法,最高可以提速900倍

作者:Nirmalya Ghosh 来源:deephub 转自:数据STUDIO在本文中,我将介绍一些简单的方法,可以将Python for循环的速度提高1.3到900倍。Python内建的一个常用功能是timeit模块。下面几节中我们将使用它来度量循环的当前性能和改进后的性能。对于每种方法,我们通过运行测试来建立基线,该测试包括在10次测试运行中运行被测函数100K次(循环),然后计算每个循环的...

fengdu78的博客 564

使用 MATLAB/Simulink 构建一个 基于神经网络控制的单相并网逆变器系统

单相并网逆变器广泛应用于户用光伏小型储能和电动汽车V2G等场景。其核心控制目标是实现高质量的并网电流,即电流与电网电压同频同相(单位功率因数),且总谐波畸变率 (THD)极低。非线性因素:电力电子器件的开关死区非线性电感寄生参数。参数不确定性:滤波器元件(L, C)的老化温漂。电网扰动:电压谐波频率波动不平衡。模型依赖性:PI、PR等控制依赖于精确的系统模型,模型失配导致性能下降。动态响应:在光照突变(光伏)或负载突变(储能)下,需快速、无超调地响应。

xiaoheshang_123的博客 274

强!提升Python循环的12种方法,最高可以提速1.3到900倍!

本文介绍了一些简单的方法,将Python for循环的提升了1.3到970x。使用Python内置的map()函数代替显式的for循环加速970x使用set代替嵌套的for循环加速498x[技巧#3]使用itertools的filterfalse函数加速131x使用lru_cache函数使用Memoization加速57x。

2301_81967508的博客 721

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

加速 Python for 循环

本文介绍了一些简单的方法,将Python for循环的提升了1.3到970x。使用Python内置的map()函数代替显式的for循环加速970x使用set代替嵌套的for循环加速498x[技巧#3]使用itertools的filterfalse函数加速131x使用lru_cache函数使用Memoization加速57x。

l422402的博客 1088

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

上一篇: 免费送一本帮你进互联网大厂的书
下一篇: Python 还能用来剪视频?!
codingpy
博客等级 码龄11年 1873粉丝 104原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值