范围和 xrange 函数之间的差异

在 Python 2 中, range 函数返回一个列表,而 xrange 创建一个特殊的 xrange 对象,这是一个不可变序列,与其他内置序列类型不同,它不支持切片,既没有 index 也没有 count 方法:

Python 2.x >= 2.3

print(range(1, 10))
# Out: [1, 2, 3, 4, 5, 6, 7, 8, 9]

print(isinstance(range(1, 10), list))
# Out: True

print(xrange(1, 10))
# Out: xrange(1, 10)

print(isinstance(xrange(1, 10), xrange))
# Out: True

在 Python 3 中,xrange 被扩展为 range 序列,因此现在创建了一个 range 对象。没有 xrange 类型:

Python 3.x >= 3.0

print(range(1, 10))
# Out: range(1, 10)

print(isinstance(range(1, 10), range))
# Out: True

# print(xrange(1, 10))
# The output will be:
#Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
#NameError: name 'xrange' is not defined

另外,从 Python 3.2 开始,range 也支持切片,indexcount

print(range(1, 10)[3:7])
# Out: range(3, 7)
print(range(1, 10).count(5))
# Out: 1
print(range(1, 10).index(7))
# Out: 6

使用特殊序列类型而不是列表的优点是解释器不必为列表分配内存并填充它:

Python 2.x >= 2.3

# range(10000000000000000)
# The output would be:
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
# MemoryError

print(xrange(100000000000000000))
# Out: xrange(100000000000000000)

由于通常需要后一种行为,因此在 Python 3 中删除了前者。如果你仍想在 Python 3 中使用列表,则只需在 range 对象上使用 list() 构造函数:

Python 3.x >= 3.0

print(list(range(1, 10)))
# Out: [1, 2, 3, 4, 5, 6, 7, 8, 9]

兼容性

为了保持 Python 2.x 和 Python 3.x 版本之间的兼容性,你可以使用外部包 futurebuiltins模块来实现向前兼容性向后兼容性 ** **

Python 2.x >= 2.0

#forward-compatible
from builtins import range

for i in range(10**8):
    pass

Python 3.x >= 3.0

#backward-compatible
from past.builtins import xrange

for i in xrange(10**8):
    pass

future 库中的 range 支持所有 Python 版本中的切片,indexcount,就像 Python 3.2+中的内置方法一样。