范围和 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
也支持切片,index
和 count
:
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 版本之间的兼容性,你可以使用外部包 future
中的 builtins
模块来实现向前兼容性和向后兼容性 : ** **
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 版本中的切片,index
和 count
,就像 Python 3.2+中的内置方法一样。