[英]strange xrange() behavior in Python 2
I am familiar with the difference between range()
and xrange()
. 我熟悉
range()
和xrange()
之间的区别。 I noticed something weird with xrange()
: 我注意到
xrange()
很奇怪:
>>> xrange(1,10,2)
xrange(1, 11, 2)
>>> xrange(1,10,4)
xrange(1, 13, 4)
Functionally, it is correct: 从功能上讲,这是正确的:
>>> for item in xrange(1,10,4):
... print item
...
1
5
9
>>>
However, as you can see, the stop value in the returned xrange
object is the next higher value after the last legal value. 但是,如您所见,返回的
xrange
对象中的停止值是最后一个合法值之后的下一个更高的值。 Any reason why? 有什么原因吗?
range()
which now provides the same functionality in Python 3 as xrange
in Python 2 behaves as expected: range()
现在在Python 3中提供了与Python 2中的xrange
相同的功能:
>>> range(1,10,4)
range(1, 10, 4)
>>> range(1,10,2)
range(1, 10, 2)
>>>
The stop value of a range
or xrange
is always exclusive. range
或xrange
的终止值始终是唯一的。
Quote from the docs (Python 2): 引用文档 (Python 2):
If
step
is positive, the last element is the largeststart + i * step
less thanstop
;如果
step
为正,则最后一个元素为最大start + i * step
小于stop
; ifstep
is negative, the last element is the smalleststart + i * step
greater thanstop
.如果
step
是否定的,最后一个元素是最小的start + i * step
大于stop
。
And for Python 3 : 对于Python 3 :
For a positive
step
, the contents of a range r are determined by the formular[i] = start + step*i
wherei >= 0
andr[i] < stop
.对于正
step
,范围r的内容由下式确定r[i] = start + step*i
,其中i >= 0
和r[i] < stop
。For a negative
step
, the contents of the range are still determined by the formular[i] = start + step*i
, but the constraints arei >= 0
andr[i] > stop
.对于负
step
,范围的内容仍由公式r[i] = start + step*i
,但约束条件为i >= 0
且r[i] > stop
。
About the second part of your question regarding the repr()
of the xrange
: 关于有关
xrange
的repr()
的问题的第二部分:
xrange(1, 10, 4)
and xrange(1, 13, 4)
are identical and repr()
for native python objects usually returns valid python code to recreate the object. xrange(1, 10, 4)
xrange(1, 13, 4)
xrange(1, 10, 4)
和xrange(1, 13, 4)
相同,并且本机python对象的repr()
通常返回有效的python代码以重新创建该对象。 This does not need to be the exactly same python code that initially created the object. 这不必是最初创建该对象的完全相同的python代码。
Does it really matter? 真的有关系吗?
The effect is the same. 效果是一样的。 Neither 10 nor 11 is included in the output of
xrange()
, and xrange(1, 11, 2)
is equivalent to xrange(1, 10, 2)
. xrange()
的输出中既不包含10也不包含11,并且xrange(1, 11, 2)
等效于xrange(1, 10, 2)
。
The Python 2 range type (the result of xrange()
) stores the range length, not the end value, so to create the repr
output it calculates that end value for you. Python 2范围类型(
xrange()
的结果)存储范围长度,而不是最终值,因此要创建repr
输出,它将为您计算该最终值。 And because you used a step value, the calculation shows the result of the formula start + length * step
. 并且由于使用了步长值,因此计算将显示公式
start + length * step
。 For the implementation, the length is the more important value, the end
value can safely be discarded and recalculated as needed. 对于实现,长度是更重要的值,可以安全地舍弃
end
值,并根据需要重新计算。
So, when you create xrange(1, 10, 2)
, it calculates the range length and stores that instead of the end value: 因此,当您创建
xrange(1, 10, 2)
,它将计算范围长度并将其存储,而不是最终值:
if (step > 0 && lo < hi)
return 1UL + (hi - 1UL - lo) / step;
else if (step < 0 && lo > hi)
return 1UL + (lo - 1UL - hi) / (0UL - step);
else
return 0UL;
The Python 3 Range object stores the end value in addition to the length, so you can query the object for it and display it in the repr
output. 除了长度,Python 3 Range对象还存储最终值,因此您可以查询该对象并将其显示在
repr
输出中。
xrange(1, 10, 4)
is equivalent to xrange(1, 13, 4)
. xrange(1, 10, 4)
等效于xrange(1, 13, 4)
。 To use your example: 使用您的示例:
>>> for item in xrange(1,13,4):
... print item
...
1
5
9
>>>
xrange
in Python 2 canonicalizes the start, stop, step
arguments. Python 2中的
xrange
规范化了start, stop, step
参数。 Internally, the xrange
implementation stores the triple start, step and length (number of elements in the xrange
object) instead of start, step and stop. 在内部,
xrange
实现存储三重开始,步长和长度( xrange
对象中的元素数),而不是开始,步进和停止。 Here is how xrange.__repr__()
is implemented [1]: 这是
xrange.__repr__()
的实现方法[1]:
rtn = PyString_FromFormat("xrange(%ld, %ld, %ld)",
r->start,
r->start + r->len * r->step,
r->step);
[1] https://github.com/replit/empythoned/blob/master/cpython/Objects/rangeobject.c [1] https://github.com/replit/empythoned/blob/master/cpython/Objects/rangeobject.c
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.