在'xrange'中使用动态计算的'step'

时间:2017-07-18 12:02:50

标签: python

假设我有:

def func(n):
    for i in range(1,100000,2*n+3):
        ...

很明显,step = 2*n+3部分计算一次。

xrange

是否保证相同?

根据this answerxrange是一个懒惰评估的序列对象。

所以问题基本上是 - 哪个部分懒惰评估?

只是start <= stop部分,还是step部分?

我尝试了一个简单的测试来确定答案:

n = 1
for a in xrange(0,100,n):
    print a
    n += 1

此测试清楚地表明在每次迭代时都不会重新评估n

但是我怀疑n表达式中的xrange可能与n之前声明的xrange的范围不同。“ / p>

谢谢。

5 个答案:

答案 0 :(得分:4)

range()xrange()都不关心步骤值的推导方式;执行表达式并将表达式结果传递给调用,即range()xrange()或任何其他可调用对象。

那是因为(...)也是一个表达;它是call expression;传递给调用的参数是在结果传递给调用之前计算的所有表达式。这里所谓的内容并不重要。

TLDR; xrange()对象传递表达式的结果,而不是表达式本身。只要该结果是一个整数对象,它就会被对象存储(作为一个不可变的值)来基于虚拟序列。

答案 1 :(得分:2)

xrange懒惰地工作的事实意味着 参数在<#34;&#34;&#34;&#34;时间 xrange(实际上xrange从来不知道表达式是什么),但是元素会被懒散地生成。因此,在您调用step 之前,xrange(..)参数实际上是计算出来的。因此,xrange(..)不知道该步骤的计算方式,因此无法要求重新评估该步骤。

虽然xrange(..)比这更复杂(因为它可以使用否定步骤等),但是一个非常基本的实现是:

def xrange(frm,to,step):
    i = frm
    while i < to:
        yield i
        i += step

答案 2 :(得分:2)

添加其他答案:测试此方法的一个好方法是提供一个函数作为步骤参数。如果要多次评估,则需要多次调用该函数。

foo was called
0
25
50
75

以上代码输出

document.getElementsByClassName()

表明步骤参数只被评估一次。

答案 3 :(得分:2)

当你将适当的参数传递给xrange()时,Python将构建一个生成器对象,它将动态地计算值&#34;。

构造并返回该生成器对象后,将设置该对象。 它不再关心最初用于计算其构造函数参数的变量是否发生了变化

同样的原则不仅适用于xrange(),也适用于其他可调用对象。一旦将参数传递给可调用函数,Python就会使用任何变量的当前值计算表达式,并将结果传递给callable。如果用于计算可调参数的参数的任何变量的值已更改,则Python不关心,因为仅使用了变量的当前值。 每次传递给它的表达式中使用的变量发生变化时,Python都不会重新计算函数的参数

>>> n = 10
>>> xr = xrange(n)
>>> n += 1
>>> n
11
>>> list(xr)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>

答案 4 :(得分:1)

懒惰评估并不意味着您可以在评估过程中更改评估;在迭代step时,您正在处理使用您提供的参数创建的生成器。它在迭代期间无法更改其Rails.logger.info('Event happened', { event_id: '...', email: '...', ...} ) ,至少不能使用内置的{。}}。