【发布时间】:2015-09-22 12:27:21
【问题描述】:
需要了解range(0,2)和list(range(0,2))的区别,使用python2.7
两者都返回一个列表,那么究竟有什么区别?
【问题讨论】:
标签: python python-2.7 python-3.x
需要了解range(0,2)和list(range(0,2))的区别,使用python2.7
两者都返回一个列表,那么究竟有什么区别?
【问题讨论】:
标签: python python-2.7 python-3.x
在 Python 3.x 中,
range(0,3) 返回一个不可变的可迭代对象类,让您可以对其进行迭代,它不会生成列表,并且它们不会将范围内的所有元素存储在内存中,而是动态生成元素(如您正在迭代它们),而 list(range(0,3)) 生成一个列表(通过迭代所有元素并在内部附加到列表)。
例子-
>>> range(0,3)
range(0, 3)
>>> list(range(0,3))
[0, 1, 2]
理想情况下,如果您只想迭代该值范围,range(0,3) 会比 (list(range(0,3)) 快,因为后者在开始迭代之前会产生生成列表的开销。
在 Python 2.x 中,range(0,3) 生成一个列表,而我们也有一个 xrange() 函数,它具有与 Python 3.x 中的 range() 函数类似的行为(xrange 在 Python 3.x 中被重命名为 range )
对于 Python 3.5,来自 documentation -
Range 对象实现 collections.abc.Sequence ABC,并提供包含测试、元素索引查找、切片和支持负索引等功能
所以你可以做这样的事情 -
>>> range(0,10)[5]
5
>>> range(0,10)[3:7]
range(3, 7)
>>> 5 in range(6,10)
False
>>> 7 in range(1,8)
True
所有这些都是常数时间操作,从这个测试中可以看出-
In [11]: %timeit a = xrange(0,1000000)[1000]
1000000 loops, best of 3: 342 ns per loop
In [12]: %timeit a = xrange(0,1000000)[10000]
1000000 loops, best of 3: 342 ns per loop
In [13]: %timeit a = xrange(0,1000000)[100000]
1000000 loops, best of 3: 342 ns per loop
In [14]: %timeit a = xrange(0,1000000)[999999]
1000000 loops, best of 3: 342 ns per loop
In [15]: %timeit a = xrange(0,10000000)[9999999]
1000000 loops, best of 3: 339 ns per loop
In [16]: %timeit a = xrange(0,1000000000000)[9999999999]
1000000 loops, best of 3: 341 ns per loop
【讨论】:
range(x,y) 类似于生成器吗?自从我第一次看到这种行为以来,我一直想知道的事情......
基本上,区别在于range(0, 2) 是生成器函数,list(range(0, 2)) 是实际列表。
在循环中使用生成器函数。例如,文件的生成器函数将逐行读取一个非常大的文件。
def gen():
for line in open("hugefile.csv", "r"):
yield line #Gives back the line every time it is read, but forgets that line after
for line in gen():
print(line)
这将打印每一行而不会使计算机的 RAM 过载,因为您只是在这两个函数中一一读取。但是,如果我们做类似
def readEntireFile():
return [line for line in open("hugefile.csv", "r")] #Python has lazy ways of making lists, this is the same as returning a list with all the lines in the file
for line in readEntireFile():
print(line)
第二部分看起来一样,但事实并非如此。最初,我们循环遍历文件中的每一行,并在完成后转到下一行。在这里,Python 有一个所有行的列表:/,想象一下用 10GB 的文件来做这件事!你的代码会崩溃。
现在,让我们回到 range() 和 list(range())
执行for x in range(0, 6): 会使我们转到范围内的下一个数字,而完全忘记前一个数字(螺丝文法)。
但是,执行for x in list(range(0, 6)): 将整个数字列表保留在内存中,并且与执行相同
numlist = [x for x in range(6)]
for x in numlist:
print(x)
当您需要代码中的整个数据列表时,请使用 list 方法。但是,当您一次只需要一条数据时(最简单的示例,以块的形式复制文件),请使用生成器函数来节省空间。您可以仅使用 54 mb 复制文件的每 100 万行(假设您没有非常长的行)。但是,如果我们有一个 2kb 的小文件,我们可以在没有生成器的情况下复制那个东西。这不值得花时间,而且在这种情况下速度较慢。
【讨论】:
两个命令都返回Python 2.x 中的列表。但在Python 3.x、range() returns an immutable sequence 中,不是列表。它用于迭代和循环。
【讨论】:
在python3.x中,范围有自己的类型
>>> range(1)
range(0, 1)
>>> type(range(1))
<class 'range'>
因此,如果您想在 for 循环中使用 range(),那很好。但是您不能将它 purely 用作列表对象。您需要将其转换为列表才能执行此操作。
Python2 示例:
>>> L = range(10)
>>> L[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Python3 示例:
>>> L = range(10)
>>> L[::-1]
range(9, -1, -1)
【讨论】:
>>> range(0,3)[1:3] range(1, 3)
range() 是一种序列类型,具有与列表和元组相同的操作(除了 concat 和重复)docs.python.org/3/library/…
Range 生成一个 'range' 类的对象
是否持续存在取决于是否分配
a = range(10)
print(type(a))
print(a[0])
print(type(a[0]))
输出:
<class 'range'>
0
<class 'int'>
输出在功能上是一个不可变的有序整数容器。
从语义上讲,它是一个整数元组,但为了提高效率,Python 将其实现为一个单独的“生成器”类而不是类元组。
这是一个很好的例子,说明由于缺乏编译,Python 无法隐藏实现细节,程序员必须意识到这些细节。
【讨论】: