为什么没有为浮点数优化Python 3范围对象?

时间:2016-05-11 18:40:32

标签: python python-3.x optimization range

从前一个问题跳出来,我问了一会儿:

Why is 1000000000000000 in range(1000000000000001) so fast in Python 3?

如果你这样做:

1000000000000000.0 in range(1000000000000001)

...很明显range尚未优化以检查float是否在指定范围内。

我认为我理解range的目的只是与int合作 - 所以你不能,例如,做这样的事情:

1000000000000 in range(1000000000000001.0)
# error: float object cannot be interpreted as an integer

或者这个:

1000000000000 in range(0, 1000000000000001, 1.0) 
# error: float object cannot be interpreted as an integer

然而,无论出于何种原因,决定允许这样的事情:

1.0 in range(1)

很明显,1.0(以及1000000000000.0以上)未被强制转换为int,因为int优化也适用于那些人。

我的问题是,为什么不一致,以及为什么没有优化float?或者,或者,为什么上述代码不会产生与前面示例相同的错误的原因是什么?

除了优化int之外,这似乎是一个明显的优化。我猜测有一些细微的问题妨碍了这种优化的干净实施,或者有一些理由说明为什么你实际上不想包含这样的优化。或者两者都可能。

编辑:为了澄清这个问题,以下所有语句也评估为False

3.2 in range(5)
'' in range(1)
[] in range(1)
None in range(1)

这对我来说似乎是出乎意料的行为,但到目前为止肯定没有不一致。但是,以下评估为True

1.0 in range(2.0)

如前所示,与上述类似的结构尚未优化。

这似乎不一致 - 在评估的某个时刻,1.0(或我原始示例中的1000000000001.0)被强制转换为int。这是有道理的,因为将float中的.0结尾转换为int是很自然的事情。但是,问题仍然存在:如果转换为int,为什么1000000000000.0 in range(1000000000001)未被优化?

1 个答案:

答案 0 :(得分:5)

此处无不一致。浮点值不能被强制转换为整数,只能以相反的方式工作。因此,range()在测试遏制时不会隐式地将浮点数转换为整数。

range()对象是序列类型;它包含离散的整数值(尽管是虚拟的)。因此,它必须支持任何对象的包含测试,该对象可能测试相同。以下也适用:

>>> class ThreeReally:
...     def __eq__(self, other):
...         return other == 3
...
>>> ThreeReally() in range(4)
True

这必须对范围内的所有可能值进行全面扫描,以测试与每个包含的整数的相等性。

但是,只有在使用实际整数时才能应用优化,因为这是range()对象可以知道的唯一类型如果没有转换,价值将被视为相等。