列表中的生成器与链接生成器和内存消耗?

2024-10-01 04:48:23 发布

您现在位置:Python中文网/ 问答频道 /正文

有人能在这些例子中解释发电机是如何工作的吗?在

在本例中来自http://www.dabeaz.com/generators/index.html

wwwlog = open("access-log")
bytecolumn = (line.rsplit(None,1)[1] for line in wwwlog)
bytes = (int(x) for x in bytecolumn if x != '-')
print "Total", sum(bytes)
  1. 当我们像这样链接生成器时,在sum()之前,除了代码对象创建之外,还有什么真正的工作发生吗?在
  2. 我们为什么要这么做线.分割(无,1)[1] 和int(x)分开-这样做有好处吗?在

在这个例子中(x*x代表x范围内的x(1100000000))

  1. 当解释器计算这个表达式时,python2中的range(1100000000)是否计算出来?在
  2. 这是在该语句期间还是在生成器的第一次运行期间发生的
  3. 这在Python3中有什么不同吗?在

我有这个疑问的原因是:

^{2}$

与列表或场景相比,使用生成器有什么优势吗?在


Tags: incomhttpforbyteswwwline发电机
2条回答

1.当我们像这样链式生成器时,在执行sum()之前是否会有任何实际的工作发生?在

Generator expression return an object that produces results on demand instead of building a result list so your answer is No (but it still depends on your mean about real work).

2.为什么我们需要分开做line.split(None,1)[1]和{}这样做有好处吗?在

it just make your code more readable and increase flexibility (based on what you may do with that expression), you can do it in one line :

(int(line.rsplit(None,1)[1]) for line in wwwlog if ine.rsplit(None,1)[1] != '-') 

在这个例子中(x*x代表x范围内的x(1100000000))

3.Python2是否计算了范围(1100000000)?在

yes it dose , instead in python 2 you can use xrange that return an iterator.

4.如果是这样,是在该语句期间还是在发生器首次运行期间

...?

5.Python3中的情况不同吗?在

in python 3 meany of built-in functions return an iterator like open or range

为了回答您的第四个问题和您在评论中提出的问题,我认为learning python by Mark Lutz的这一部分可能会有所帮助:

生成器表达式:迭代器满足理解

在Python的所有最新版本中,迭代器和列表理解的概念是 结合了语言的一个新功能,生成器表达式。句法上,gen- 运算符表达式与普通的列表理解类似,但它们都包含在 用括号代替方括号:

^{pr2}$

事实上,至少在函数的基础上,对列表理解进行编码本质上是相同的 将生成器表达式包装在列表内置调用中,以强制它生成 立即生成列表:

>>> list(x ** 2 for x in range(4))
[0, 1, 4, 9]

列表理解等价

然而,在操作上,生成器表达式与构建表达式有很大不同 结果列表在内存中,它们返回一个生成器对象,该对象反过来支持 迭代协议在任何迭代上下文中一次生成一个结果列表:

>>> G = (x ** 2 for x in range(4))
>>> next(G)
0
>>> next(G)
1
>>> next(G)
4
>>> next(G)
9
>>> next(G)
Traceback (most recent call last):
...more text omitted...
StopIteration

我们通常不会在生成器ex的引擎盖下看到下一个迭代器机器- 这样的压力是因为for循环会自动为我们触发:

>>> for num in (x ** 2 for x in range(4)):
...
print('%s, %s' % (num, num / 2.0))
...
0, 0.0
1, 0.5
4, 2.0
9, 4.5

正如我们已经了解到的,每个迭代上下文都会这样做,包括sum、map和 排序的内置函数;列表理解;以及我们学习的其他迭代上下文 关于第14章,比如any、all和list内置函数。 请注意,在生成器表达式周围不需要括号(如果需要的话) 包含在其他括号中的唯一项,如函数调用的项。额外的帕伦- 但是,在第二次调用sorted:

>>> sum(x ** 2 for x in range(4))
14
>>> sorted(x ** 2 for x in range(4))
[0, 1, 4, 9]
>>> sorted((x ** 2 for x in range(4)), reverse=True)
[9, 4, 1, 0]
>>> import math
>>> list( map(math.sqrt, (x ** 2 for x in range(4))) )
[0.0, 1.0, 2.0, 3.0]

生成器表达式主要是一种内存空间优化,而不是- 要求一次构造整个结果列表,如方括号中的列表 理解是正确的。它们在实践中也可能运行得稍慢,所以它们可能是 最好只用于非常大的结果集。关于per的更权威的声明- 不过,formance必须等待我们在本章后面编写的计时脚本。在

  1. 生成器是惰性的,因此在迭代它们之前什么都不会发生(例如使用sum)。在
  2. 它只是让它更具可读性。如果你想这样写的话: bytes = (int(x) for x in (line.rsplit(None,1)[1] for line in wwwlog) if x != '-')
  3. 是的,在python2中range返回一个列表,您需要xrange来生成类似生成器的对象。在
  4. 它是在遍历生成器时计算的,在此之前不执行任何操作。在
  5. 是的,在python3中range的行为类似于python2的xrange。同样的情况也发生在其他函数上,比如mapfilter。在

生成器的主要优点是不会一次存储全部内容。它们的主要缺点是只能迭代一次。在

相关问题 更多 >