Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么范围(0)=范围(2,2,2)在Python3中是真的?_Python_Python 3.x_Range_Identity_Python Internals - Fatal编程技术网

为什么范围(0)=范围(2,2,2)在Python3中是真的?

为什么范围(0)=范围(2,2,2)在Python3中是真的?,python,python-3.x,range,identity,python-internals,Python,Python 3.x,Range,Identity,Python Internals,为什么在Python3中,用不同值初始化的范围彼此比较相等 当我在解释器中执行以下命令时: >>> r1 = range(0) >>> r2 = range(2, 2, 2) >>> r1 == r2 True 结果是True。为什么会这样?为什么具有不同参数值的两个不同的范围对象被视为相等?范围对象是特殊的: Python将对象比较为。这本质上意味着,比较不会评估它们如何表示给定序列,而是评估它们表示的内容 开始、停止和步骤参数完全不同这

为什么在Python3中,用不同值初始化的范围彼此比较相等

当我在解释器中执行以下命令时:

>>> r1 = range(0)
>>> r2 = range(2, 2, 2)
>>> r1 == r2
True
结果是
True
。为什么会这样?为什么具有不同参数值的两个不同的
范围
对象被视为相等?

范围对象是特殊的: Python将对象比较为。这本质上意味着,比较不会评估它们如何表示给定序列,而是评估它们表示的内容

开始
停止
步骤
参数完全不同这一事实在这里没有什么区别,因为它们在展开时都表示一个空列表:

例如,第一个
范围
对象:

list(range(0))  # []
list(range(2, 2, 2)) # []
第二个
范围
对象:

list(range(0))  # []
list(range(2, 2, 2)) # []
两者都表示一个空列表,由于两个空列表比较相等(
True
),因此表示它们的
范围对象也将相等

因此,您可以拥有外观完全不同的
范围
对象;如果它们代表相同的序列,它们将进行相等的比较:

两者都表示具有单个元素的列表
[1]
,因此这两个元素的比较也将相等


不,
范围
对象非常特殊: 但是请注意,即使比较没有评估它们如何表示序列,也可以使用单独使用
开始
步骤
的值以及
范围
对象的
长度
来获得比较结果;这对比较的速度有着非常有趣的影响:

r0 = range(1, 1000000)    
r1 = range(1, 1000000)

l0 = list(r0)    
l1 = list(r1)
极快的速度:

%timeit r0 == r1
The slowest run took 28.82 times longer than the fastest. This could mean that an intermediate result is being cached 
10000000 loops, best of 3: 160 ns per loop
另一方面,列表

%timeit l0 == l1
10 loops, best of 3: 27.8 ms per loop


所述,这仅适用于Python 3中的范围对象。Python2
range()
是一个普通的ol'函数,它返回一个列表,而
2.x
对象没有Python3中
range
对象所具有的比较功能()

查看直接从Python 3
范围
对象的源代码中获取引号。其中记录了两个不同范围之间的比较实际需要的内容:简单快速的操作。该功能用于for
EQ
NE
情况,并分配给

我相信
range_equals
的实现非常可读(因为它非常简单),可以添加到这里:

/*r0和r1是指向RangeObject的指针*/
/*检查指针是否指向同一对象,例如:
>>>r1=r2=范围(0,10)
>>>r1==r2
显然,返回True*/
如果(r0==r1)
返回1;
/*比较范围的长度(如果相等)
检查仍在继续。如果不是,则返回False*/
cmp_结果=PyObject_RichCompareBool(r0->length,r1->length,Py_EQ);
/*向调用者返回False或error
>>>范围(0,10)=范围(0,10,2)
这里失败了*/
如果(cmp_结果!=1)
返回cmp_结果;
/*查看范围是否有长度(非空)。如果长度为0
然后由于前面的检查,另一个范围的长度为
等于0。他们是平等的*/
cmp_结果=PyObject_Not(r0->长度);
/*向调用者返回True或error。
>>>范围(0)=范围(2,2,2)#真
(对)在这里被抓住。长度都是零*/
如果(cmp_结果!=0)
返回cmp_结果;
/*比较范围的起始值(如果不匹配)
那么我们不是在处理相等的范围*/
cmp\u结果=PyObject\u RichCompareBool(r0->start,r1->start,Py\u EQ);
/*向调用者返回False或error。
如果镜头相等,则检查其起始值
>>>范围(0,10)=范围(10,20)#错误
长度相等且非零,步长不匹配*/
如果(cmp_结果!=1)
返回cmp_结果;
/*检查长度是否等于1。
如果起点相同且长度为1,则表示相同的顺序:
>>>范围(0,10,10)=范围(0,20,20)#真*/
一个=塔龙(1);
如果(!一)
返回-1;
cmp\u结果=PyObject\u richcomarebool(r0->length,one,Py\u EQ);
Py_DECREF(一个);
/*向调用者返回True或error*/
如果(cmp_结果!=0)
返回cmp_结果;
/*最后,比较一下他们的步骤*/
返回PyObject\u richcomarebool(r0->step,r1->step,Py\u EQ);
我也在这里散布了我自己的一些评论;查看Python的等价物。

res=range(0)==range(2,2,2)

其中:

range(0)
表示从
0
0
-
0
步骤的范围(此处
step
等于默认值
1
),列表中没有值

range(2, 2, 2)
表示从
2
2
的范围,步长等于
2
,列表中没有值

range(2, 2, 2)
因此,这些范围实际上是相等的

range(0)
返回
range(0,0)
。步骤1从0开始到0,这是未定义的,因为第三个参数[默认情况下]不能为0。使用1无法到达0。没有适当的计数器操作,因此为0

range(2,2,2)
返回
range(2,2,2)
。从2开始到2,但步骤为2。这也是,基本上是0,因为你什么都不算

range(0) == range(2,2,2) 
正确完全相同。

直接引用(强调我的):

测试范围对象是否与==和!=相等将它们比较为 序列。也就是说,如果两个范围对象 表示相同的值序列。(请注意,两个范围对象 比较相等可能有不同的开始、停止和步骤 属性,例如范围(0)=范围(2,1,3)或范围(0,3,2) ==范围(0、4、2)

如果将
range
s与“same”列表进行比较,就会得到不等式,如