首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Python技巧:避免大列表理解,生成器表达式往往更有用~

众所周知,Python列表推导的工作原理比循环要快。但是,在某些情况下,它们可能会严重破坏程序的性能,甚至导致内存崩溃。在这些情况下,需要考虑使用生成器表达式。

从语法上讲,这两个非常相似。它们之间的唯一区别是,您可以使用声明列表推导[]和,使用来声明生成器表达式(),就像这样:

list_compr = [x**2 for x in range(10)]

gen_expr = (x**2 for x in range(10)

关键是要对列表理解进行评估。在交互式shell中定义列表理解后,我们将获得结果列表:

>>> [x**2 for x in range(10)]

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

相反,生成器表达式将返回生成器对象:

>>> (x**2 for x in range(10))

生成器正常运行,需要使用next()方法,迭代生成器表达式或使用类似list(),set()或tuple()方法。

在上面的示例中,使用列表推导实际上更可取。当内存不是问题时,它们将优于生成器表达式。

当需要处理大量数据时,就会出现问题,因为列表推导会立即将所有输出的数据存储在内存中(就像我们在代码中看到的那样)。

相反,生成器是一种概念,旨在一次生成一个(产量)结果,而不是将整个数据结构加载到内存中。这样就可以处理庞大的数据集,而不会出现内存使用量激增的风险。

生成器的优点:

1.表情与像功能特别有用sum(),min()和max()。

2.生成器表达式可以轻松地链接(组合)在一起,从而创建一个数据管道,可以逐项处理大量数据。

缺点:不适用于需要多次使用这些值的情况,因为一旦生成器用尽,就无法访问其生成的值。

执行一个小型基准测试,如何将生成器的表达式链接在一起。我们将要进行以下操作:

1)计算文件中每行的长度,

2)然后从每行长度中提取平方根,

3)求平方根。

我使用.txt格式的“夏洛克·福尔摩斯历险记”,你们可以选择其他一些文本文件。

让我们首先使用列表推导:

import time

execution = []

for i in range(100):

 start = time.time()

 filename = 'Sherlock Holmes.txt'

 lengths = [len(line) for line in open(filename)]

 roots = [x**0.5 for x in lengths]

 print(sum(roots))

 end = time.time()

 execution.append(end-start)

print(f'Avg execution time with list comprehensions: '

   f'')

使用生成器表达式,此代码看起来几乎相同:

import time

execution = []

for i in range(100):

 start = time.time()

 filename = 'Sherlock Holmes.txt'

 lengths = (len(line) for line in open(filename))

 roots = (x**0.5 for x in lengths)

 print(sum(roots))

 end = time.time()

 execution.append(end-start)

print(f'Avg execution time with generator expressions: '

   f'')

第二个块将以不同的方式运行。Python不会在每一行上产生整个结果,而是从文件中读取一行,然后测量其长度,然后将其加到总和上。然后,解释器将继续进行下一行,依此类推。这正是将生成器表达式链接(组成)到数据管道中的意思。

因此,让我们运行两个版本:

Avg execution time with list comprehensions: 0.00486

Avg execution time with generator expressions: 0.00530

如您所见,在此数据集上,列表理解的运行速度更快。但是,如果我在包含超过1000万行的文件上运行相同的代码,结果将有所不同(我只是将文本复制粘贴到Sherlock Holmes中多次):

Avg execution time with list comprehensions: 4.26855

Avg execution time with generator expressions: 3.79113

如您所见,在这种情况下,生成器表达式已被理解:

结论

综上所述,生成器表达式在处理大型数据集时效率更高,并且可以帮助您的程序避免崩溃。而且,它们很容易链接在一起,从而创建了能够一一生成结果值的数据管道。

同时,在较小的数据(较小的数据-取决于计算机)上,列表理解通常胜过生成器表达式,如果您需要多次访问生成的数据,则列表理解会更有用。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20201210A08J3F00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券