掌握这9个技巧,让Python代码快如闪电(上)

9个使Python代码更快的微妙技巧。

微信搜索关注《Python学研大本营》,加入读者群,分享更多精彩

掌握这9个技巧,让Python代码快如闪电(上)_第1张图片

前言

掌握这9个技巧,让Python代码快如闪电(上)_第2张图片

图片来自Wallhaven

“Python太慢了。”

这种观点在关于编程语言的讨论中经常出现,经常掩盖了Python的众多优点。

事实是,如果能以Pythonic的方式编写Python代码,它是很快的。

细节决定成败。经验丰富的Python开发者掌握了一系列微妙而强大的技巧,可以显著提高代码的性能。

这些技巧乍看之下似乎微不足道,但它们可以带来效率的大幅提升。让我们深入了解其中的9种方法,改变编写和优化Python代码的方式。

1. 更快的字符串连接:巧妙选择“join()”或“+

如果有大量字符串等待处理,字符串连接将成为Python程序的瓶颈。

基本上,Python有两种字符串连接的方式:

  1. 使用join()函数将一组字符串合并为一个字符串。

  2. 使用++=符号将每个单独的字符串添加到一个字符串中。

那么哪种方式更快呢?

现在,让我们定义3个不同的函数来连接相同的字符串:

mylist = ["Yang", "Zhou", "is", "writing"]


# 使用'+'
def concat_plus():
    result = ""
    for word in mylist:
        result += word + " "
    return result


# 使用'join()'
def concat_join():
    return " ".join(mylist)


# 直接连接而不使用列表
def concat_directly():
    return "Yang" + "Zhou" + "is" + "writing"

根据你的第一印象,你认为哪个函数最快,哪个最慢?

真正的结果可能会让你惊讶:

import timeit

print(timeit.timeit(concat_plus, number=10000))
# 0.002738415962085128
print(timeit.timeit(concat_join, number=10000))
# 0.0008482920238748193
print(timeit.timeit(concat_directly, number=10000))
# 0.00021425005979835987

如上所示,对于连接一组字符串,join()方法比在for循环中逐个添加字符串更快。

原因很简单。一方面,字符串在Python中是不可变的数据,每次+=操作都会创建一个新字符串并复制旧字符串,这在计算上成本是昂贵的。

另一方面,.join()方法专门针对连接一系列字符串进行了优化。它会预先计算出所生成字符串的大小,然后一次性创建它。因此,它避免了循环中+=操作带来的开销,从而使速度更快。

然而,在我们的测试中,速度最快的函数是直接连接字符串文字。它的高速度是由于:

  • Python解释器可以在编译时优化字符串文字的连接,将它们转换为一个单独的字符串文字。这里不涉及循环迭代或函数调用,因此是一种非常高效的操作。

  • 由于所有字符串在编译时都是已知的,Python可以非常快速地执行此操作,比在循环中进行的运行时连接或经过优化的.join()方法要快得多。

总之,如果需要连接一组字符串,请选择join()而不是+=。如果想要直接连接字符串,只需使用+即可。

2. 更快的列表创建:使用“[]”而不是“list()

创建列表并不是很难的事情。常见的两种方式是:

  1. 使用list()函数。

  2. 直接使用[]

让我们使用一个简单的代码片段来测试它们的性能:

import timeit

print(timeit.timeit('[]', number=10 ** 7))
# 0.1368238340364769
print(timeit.timeit(list, number=10 ** 7))
# 0.2958830420393497

结果显示,执行list()函数比直接使用[]要慢。

这是因为[]是一种字面量语法,而list()是一个构造函数调用。调用函数无疑需要额外的时间。

从同样的逻辑出发,在创建字典时,我们也应该使用{}而不是dict()

3. 更快的成员测试:使用集合而不是列表

成员测试操作的性能在很大程度上依赖于底层数据结构:

import timeit

large_dataset = range(100000)
search_element = 2077

large_list = list(large_dataset)
large_set = set(large_dataset)


def list_membership_test():
    return search_element in large_list


def set_membership_test():
    return search_element in large_set


print(timeit.timeit(list_membership_test, number=1000))
# 0.01112208398990333
print(timeit.timeit(set_membership_test, number=1000))
# 3.27499583363533e-05

正如上述代码所示,使用集合进行成员测试比使用列表更快。

为什么会这样呢?

  • 在Python的列表中,成员测试(列表中的元素)是通过迭代每个元素直到找到所需的元素或达到列表的末尾来完成。因此,此操作的时间复杂度为O(n)。

  • Python中的集合实现形式为哈希表。在进行成员检查(集合中的元素)时,Python使用哈希机制,其平均时间复杂度为O(1)。

这里的关键在于:在编写程序时要仔细考虑底层数据结构。正确利用合适的数据结构可以显著加快代码的运行速度。

4. 更快的数据生成:使用推导式而不是for循环

Python中有四种推导式类型:列表推导式、字典推导式、集合推导式和生成器推导式。它们不仅为创建相对数据结构提供了更简洁的语法,而且比使用for循环更高效,因为它们在Python的C实现中进行了优化。

import timeit


def generate_squares_for_loop():
    squares = []
    for i in range(1000):
        squares.append(i * i)
    return squares


def generate_squares_comprehension():
    return [i * i for i in range(1000)]


print(timeit.timeit(generate_squares_for_loop, number=10000))
# 0.2797503340989351
print(timeit.timeit(generate_squares_comprehension, number=10000))
# 0.2364629579242319

上述代码是列表推导式和for循环之间的简单速度比较。结果显示,列表推导式更快。

推荐书单

《Python从入门到精通(第3版)》

《Python从入门到精通(第3版)》从初学者角度出发,通过通俗易懂的语言、丰富多彩的实例,详细介绍了使用Python进行程序开发应该掌握的各方面技术。全书共分27章,包括初识Python、Python语言基础、运算符与表达式、流程控制语句、列表和元组、字典和集合、字符串、Python中使用正则表达式、函数、面向对象程序设计、模块、文件及目录操作、操作数据库、使用进程和线程、网络编程、异常处理及程序调试、Pygame游戏编程、推箱子游戏、网络爬虫开发、火车票分析助手、数据可视化、京东电商销售数据分析与预测、Web编程、Flask框架、e起去旅行网站、Python自动化办公、AI图像识别工具等内容。书中所有知识都结合具体实例进行介绍,涉及的程序代码都给出了详细的注释,读者可轻松领会Python程序开发的精髓,快速提升开发技能。

《Python从入门到精通(第3版)》icon-default.png?t=N7T8https://item.jd.com/14055900.html

掌握这9个技巧,让Python代码快如闪电(上)_第3张图片

精彩回顾

《数据科学必备的Python前端库Top-5》

《轻松上手,本地运行LlaMA 2的简易指南》

《8个Python开发者必备的PyCharm插件》

《数据科学不可或缺的10个Python库,让你事半功倍》

《掌握Python设计模式,SQL Alchemy助你打破ORM与模型类的束缚》

《Python进阶之路,2024年7个不可错过的技巧》

微信搜索关注《Python学研大本营》,加入读者群,分享更多精彩

访问【IT今日热榜】,发现每日技术热点

 

你可能感兴趣的:(python,c#,开发语言)