python - 在 Python 中,当 yield cost 超过返回列表时?

标签 python

在很多情况下,人们总是说“使用 yield 来延迟创建元素”。 但我认为一切都有成本,包括 yield 及其迭代器。

在 effective nord 眼中,我认为这是一个很好的问题。 所以,例如,当我得到一个函数时。

def list_gen(n):
    if n > MAGIC_NUM:
        return xrange(n)
    else:
        return range(n)

MAGIC_NUM 是多少剂量?

更新 对这个错误感到抱歉,我的意思是比较迭代器的成本和列表成本。

再次更新 请想象一个案例。是否有一个条件,即内存限制到无法创建迭代器。

哈,这个问题现在更有趣了。
再次更新 为什么创建一个迭代器和保存 yield 上下文比创建一个列表少?或迭代器的成本是多少?(对不起我的侮辱)多少字节?

最佳答案

你把几件事混在一起了。

def list_gen(n):
    i=0
    while i<n:
        yield i
        i += 1

这个函数是一个生成器。调用它会返回一个生成器对象,它是一个迭代器

迭代器是具有next() 的东西,即它可以被遍历一次。每当您执行 for i in something 时,都会使用 iter 在某些内容上创建迭代器。

def list_gen(n):
    return range(n)

def list_gen(n):
    return xrange(n)

这些函数是常规函数。一个返回一个 list,另一个返回一个 xrange 对象。列表和 xranges 都是可迭代的,即可以为它们创建多个独立的迭代器。


回到你的问题:你问的是返回一个 list 还是一个 xrange 对象。

这显然取决于!这取决于您要对结果做什么。

  • 如果您想以某种方式改变它,那么您需要一个真实的列表。直接使用range

  • 如果您只想迭代它,那么它在语义上没有区别:xrange 对象和 list 返回的 >range 将生成迭代相同序列的迭代器。

    但是,如果您使用 xrange,您将永远不会在内存中创建整个列表。如果您只想进行简单的迭代,为什么还要在内存中创建一个完整的 list 对象?您不需要在需要 for 循环时分配临时大内存缓冲区,对吧?

因此:坚持使用 xrange 是安全的,因为调用者总是可以从中创建一个 list


让我们用一个基准来确认这一点。我们想知道遍历 xranges 是否比遍历由 range 构造的列表更快(当然包括 range 调用的成本)。

代码:

import timeit

ns = [1,2,3, 5, 10, 50, 100]
print 'n', '\t', 'range', '\t', 'xrange'
for n in ns:
    t1 = timeit.timeit("for i in range({}): pass".format(n))
    t2 = timeit.timeit("for i in xrange({}): pass".format(n))
    print n, '\t', t1, '\t', t2

结果:

n       range           xrange
1       0.566222990493  0.418698436395
2       0.594136874362  0.477882061758
3       0.630704800817  0.488603362929
5       0.725149288913  0.540597548519
10      0.90297752809   0.687031507818
50      2.44493085566   1.89102105759
100     4.31189321914   3.33713522433

关于python - 在 Python 中,当 yield cost 超过返回列表时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13622551/

相关文章:

python - 如何在Tensorflow中实现预训练?如何部分使用检查点文件中保存的权重?

Python Tornado 处理程序警告禁用

python - List 方法删除列表中的最后一个元素以及所有元素

python - 覆盖 tf.floor 渐变

python - 同时在两个数据框中应用 lambda 函数

python - Pandas DataFrame 按时间戳分组

python - 无法将列表导入 MySQL - Python、Tweepy 和 MySQL.Connector

Python 日志记录 - 将日期设置为文件名

Python递归函数

python - 如何在 Django 中创建自动递增整数字段?