当前位置:首页 > 科技  > 软件

加速 Python 代码的八个优秀实用技巧

来源: 责编: 时间:2024-03-27 17:38:43 278观看
导读Python是目前世界上增长最快的编程语言之一,深受全球开发者的喜爱。其简单语法和丰富的库使得在各个领域都能得到广泛应用,比如数据科学、机器学习、信号处理、数据可视化等。然而,Python在解决复杂问题时可能会显得执行

Python是目前世界上增长最快的编程语言之一,深受全球开发者的喜爱。其简单语法和丰富的库使得在各个领域都能得到广泛应用,比如数据科学、机器学习、信号处理、数据可视化等。然而,Python在解决复杂问题时可能会显得执行速度较慢。因此,本文将探讨一些优化Python代码的方法,以加速代码运行。0yZ28资讯网——每日最新资讯28at.com

0yZ28资讯网——每日最新资讯28at.com

1.使用内置函数和库

Python标准库和第三方库(如NumPy、Pandas等)中的函数通常是用C或Cython编写的,运行速度远超纯Python代码。为了加速Python代码,可以尽量使用这些库中的向量化操作代替Python原生循环,特别是在处理数组和矩阵运算时。0yZ28资讯网——每日最新资讯28at.com

举个例子,计算Python列表中每个元素的平方。0yZ28资讯网——每日最新资讯28at.com

import numpy as npimport time# 定义一个Python列表python_list = [1, 2, 3, 4, 5]# 使用纯Python循环计算平方的时间测试def measure_time(function, argument):    start_time = time.time()    result = function(argument)    end_time = time.time()    return result, end_time - start_time# 定义纯Python循环计算平方的函数def square_elements_python(lst):    squared_lst = []    for num in lst:        squared_lst.append(num ** 2)    return squared_lst# 计算并输出纯Python循环方法执行时间和结果python_squares, python_time = measure_time(square_elements_python, python_list)print(f"纯Python循环方法: {python_squares}, Time taken: {python_time} seconds")# 转换为NumPy数组并使用向量化操作start_time = time.time()numpy_array = np.array(python_list)numpy_squares = numpy_array ** 2end_time = time.time()# 输出NumPy向量化操作执行时间numpy_time = end_time - start_timeprint(f"NumPy向量化操作: {numpy_squares.tolist()}, Time taken: {numpy_time} seconds")

输出结果如下,由此可以看出NumPy的向量化操作在执行速度上远超纯Python循环法。这是因为NumPy内部对数组操作进行了高度优化,并利用C语言编写的底层算法,极大地提高了处理效率。0yZ28资讯网——每日最新资讯28at.com

纯Python循环方法: [1, 4, 9, 16, 25], Time taken: 4.5299530029296875e-06 secondsNumPy向量化操作: [1, 4, 9, 16, 25], Time taken: 0.00020122528076171875 seconds

2.Numba JIT编译

可以使用Numba库进行即时(JIT)编译,它可以将指定的Python函数转换为高效机器码,以提升执行速度。尤其适用于数值计算密集型代码。0yZ28资讯网——每日最新资讯28at.com

例如下面的代码,sum_array函数被装饰器@jit(nopython=True)标记后,Numba会对其进行即时编译,将其转换为机器码以提升计算密集型任务的执行速度。0yZ28资讯网——每日最新资讯28at.com

import numpy as npfrom numba import jit@jit(nopython=True)def sum_array(arr: np.ndarray) -> float:    result = 0.0    for i in range(arr.shape[0]):        result += arr[i]    return resultarr = np.array([1.0, 2.0, 3.0, 4.0, 5.0])print(sum_array(arr))

3.避免不必要的copy操作

尽可能在原地修改对象,而不是创建新对象。例如,使用列表的extend()方法而非"+"操作符进行合并,使用numpy数组的切片赋值而不是重新创建数组。例如:0yZ28资讯网——每日最新资讯28at.com

# 避免:list1 = [1, 2, 3]list2 = [4, 5, 6]new_list = list1 + list2# 推荐:list1 = [1, 2, 3]list2 = [4, 5, 6]# 这里不会创建新的列表对象,而是直接在原地扩展list1list1.extend(list2)

4.使用生成器表达式代替列表推导

当不需要一次性生成所有结果,而是逐个处理时,使用生成器表达式代替列表推导式可以节省内存,因为它不会立即创建完整列表。0yZ28资讯网——每日最新资讯28at.com

例如假设有一个包含整数的列表,我们想要计算每个整数的平方并输出结果。使用列表推导式的方法如下:0yZ28资讯网——每日最新资讯28at.com

numbers = [1, 2, 3, 4, 5]squared_numbers = [num ** 2 for num in numbers]for squared_num in squared_numbers:    print(squared_num)

输出结果为:0yZ28资讯网——每日最新资讯28at.com

1491625

但是,如果我们只需要逐个处理每个平方数,而不需要将它们存储在内存中,可以使用生成器表达式代替列表推导式:0yZ28资讯网——每日最新资讯28at.com

numbers = [1, 2, 3, 4, 5]squared_numbers = (num ** 2 for num in numbers)for squared_num in squared_numbers:    print(squared_num)

输出结果与之前相同,但是使用生成器表达式可以节省内存,因为它不会一次性生成所有结果,而是逐个生成。0yZ28资讯网——每日最新资讯28at.com

5.合理利用多线程或多进程

对于CPU密集型任务,Python的多线程受GIL限制,但对于IO密集型任务或是使用多核CPU处理CPU密集型任务时,可以通过multiprocessing库开启多进程来提升效率。0yZ28资讯网——每日最新资讯28at.com

例如如下代码定义了一个计算密集型函数cpu_bound_task,然后通过multiprocessing.Pool创建了与CPU核心数量相等的进程池,并用pool.map()方法将输入列表中的任务分配给这些进程进行并行处理。0yZ28资讯网——每日最新资讯28at.com

这样,每个进程都有自己的内存空间和独立GIL,从而可以充分利用多核处理器的能力提高执行效率。0yZ28资讯网——每日最新资讯28at.com

import multiprocessing as mpdef cpu_bound_task(n):    # 模拟的CPU密集型计算任务    result = 0    for i in range(n):        result += i * i    return resultif __name__ == "__main__":    inputs = [1_000_000 + x for x in range(10)]  # 多个需要处理的数据单元    with mp.Pool(processes=mp.cpu_count()) as pool:  # 使用所有可用CPU核心数        results = pool.map(cpu_bound_task, inputs)  # 将任务分配到各个进程中并行处理    print(f"Results: {results}")

6.缓存计算结果

如果存在重复计算的情况,可以使用functools.lru_cache装饰器来缓存函数的返回结果,避免重复计算。0yZ28资讯网——每日最新资讯28at.com

如下示例使用Python标准库中的functools.lru_cache装饰器来缓存函数的结果,避免重复计算。0yZ28资讯网——每日最新资讯28at.com

from functools import lru_cache@lru_cache(maxsize=None)  # 缓存所有结果,可以根据实际情况设置缓存大小def expensive_computation(x):    # 假设这是一个计算成本很高的函数    print("Computing...")    return x ** x# 第一次调用时会执行计算result1 = expensive_computation(5)# 第二次调用时会从缓存中获取结果,不再执行计算result2 = expensive_computation(5)print(result1 == result2)

第一次调用expensive_computation(5)时,执行计算并打印"Computing...",然后返回计算结果25。第二次调用时,由于结果已被缓存,不再执行计算,直接返回上次计算得到的25。因此,result1 == result2的输出是True。0yZ28资讯网——每日最新资讯28at.com

7.利用异步IO

在处理大量IO操作时,如网络请求、文件读写等,可以利用asyncio库实现异步编程,最大化利用等待IO完成的时间进行其他任务的处理。0yZ28资讯网——每日最新资讯28at.com

例如下面例子使用Python的asyncio库来并行处理多个网络请求,它会同时发起10个对'http://example.com'的异步网络请求,并等待所有请求完成后,通过responses变量获取所有的响应结果,然后逐个调用process_response(response)函数处理这些响应。0yZ28资讯网——每日最新资讯28at.com

import asyncioasync def fetch(url):    # 异步网络请求    response = await asyncio.get_event_loop().run_in_executor(None, fetch_from_network, url)    return responseasync def main():    tasks = [fetch('http://example.com') for _ in range(10)]    responses = await asyncio.gather(*tasks)    for response in responses:        process_response(response)# 启动事件循环asyncio.run(main())

8.使用Cython或者Python-C接口

对于计算密集型的部分代码,可以使用Cython编写,将其编译为C扩展模块,或者直接使用Python的C API编写扩展模块,这种方式可以大幅提高这部分代码的执行效率。示例如下:0yZ28资讯网——每日最新资讯28at.com

首先,安装Cython并创建.pyx文件:0yZ28资讯网——每日最新资讯28at.com

# example_cython.pyxdef cython_power(int x):    return x ** x

然后,编译为C扩展模块:0yZ28资讯网——每日最新资讯28at.com

$ cython example_cython.pyx$ gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing -I/usr/include/python3.7 -o example_cython.cpython-37m-x86_64-linux-gnu.so example_cython.c

最后,在Python中导入并使用:0yZ28资讯网——每日最新资讯28at.com

import example_cython# 使用Cython优化后的函数result = example_cython.cython_power(5)print(result)

通过这种方法,Cython能够自动将Python代码转化为C代码,使得原本在Python中执行的某些计算密集型任务得以显著加速。0yZ28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-79836-0.html加速 Python 代码的八个优秀实用技巧

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 四个技巧将 Docker 镜像体积减小 90%

下一篇: 野心、梦想与科幻——浅谈外星殖民与软件工程

标签:
  • 热门焦点
  • 小米降噪蓝牙耳机Necklace分享:听一首歌 读懂一个故事

    在今天下午的小米Civi 2新品发布会上,小米还带来了一款新的降噪蓝牙耳机Necklace,我们也在发布结束的第一时间给大家带来这款耳机的简单分享。现在大家能见到最多的蓝牙耳机
  • 一个注解实现接口幂等,这样才优雅!

    场景码猿慢病云管理系统中其实高并发的场景不是很多,没有必要每个接口都去考虑并发高的场景,比如添加住院患者的这个接口,具体的业务代码就不贴了,业务伪代码如下:图片上述代码有
  • JVM优化:实战OutOfMemoryError异常

    一、Java堆溢出堆内存中主要存放对象、数组等,只要不断地创建这些对象,并且保证 GC Roots 到对象之间有可达路径来避免垃 圾收集回收机制清除这些对象,当这些对象所占空间超过
  • 破圈是B站头上的紧箍咒

    来源 | 光子星球撰文 | 吴坤谚编辑 | 吴先之每年的暑期档都少不了瞄准追剧女孩们的古偶剧集,2021年有优酷的《山河令》,2022年有爱奇艺的《苍兰诀》,今年却轮到小破站抓住了追
  • 当家的盒马,加速谋生

    来源 | 价值星球Planet作者 | 归去来自己“当家”的盒马,开始加速谋生了。据盒马官微消息,盒马计划今年开放生鲜供应链,将其生鲜商品送往食堂。目前,盒马在上海已经与
  • 超级标准版旗舰!iQOO 11S全球首发iQOO超算独显芯片

    上半年已接近尾声,截至目前各大品牌旗下的顶级旗舰都已悉数亮相,而下半年即将推出的顶级旗舰已经成为了数码圈爆料的主流,其中就包括全新的iQOO 11S系
  • iQOO Neo8系列今日官宣:首发天玑9200+ 全球安卓最强芯!

    在昨日举行的的联发科新一代旗舰芯片天玑9200+的发布会上,iQOO官方也正式宣布,全新的iQOO Neo8系列新品将全球首发搭载这款当前性能最强大的移动平台
  • 滴滴违法违规被罚80.26亿 共存在16项违法事实

    滴滴违法违规被罚80.26亿 存在16项违法事实开始于2121年7月,历经一年时间,网络安全审查办公室对“滴滴出行”网络安全审查终于有了一个暂时的结束。据“网信
  • 微软发布Windows 11新版 引入全新任务栏状态

    近日,微软发布了Windows 11新版,而Build 22563更新主要引入了几周前曝光的平板模式任务栏等,系统更流畅了。更新中,Windows 11加入了专门针对平板优化的任务栏
Top