Python 3 如何将 range 转换成列表

258

我想要创建一个包含数字 1-1000 的列表。显然这样写/读起来很烦人,因此我尝试使用范围(range)创建列表。在 Python 2 中,似乎可以这样实现:

some_list = range(1,1000)

这可能在Python 2中有效,但在Python 3中,range类似于Python 2中的xrange

有人能提供一些见解吗?


1
另外,some_list[i] == i+1,所以你可能根本不需要一个列表。 - njzk2
1
例如,有时候在绘图函数中需要提供一个列表。虽然范围可能足够,但是范围无法连接(是不可变的),因此如果您需要将默认起始值添加到所有要绘制的列表中,则需要将其转换为列表。@RikPoggi - SherylHohman
基本上,任何合理的复制列表的方法都可以接受范围作为输入,并生成相应的列表作为输出。除了基于切片的方法,因为它们只会给出另一个“范围”。 - Karl Knechtel
9个回答

338

你可以从range对象中构建一个列表:

my_list = list(range(1, 1001))
这是在Python2.x中使用生成器的方法。通常情况下,您可能不需要列表,因为可以更高效地获取my_list[i]的值(i+1),如果只需要迭代它,可以退回到range
此外,注意在Python2.x上,xrange仍然可以被索引1。这意味着Python3.x上的range也具有相同的属性21print xrange(30)[12]对于Python2.x有效。 2类似于Python3.x中1的语句是print(range(30)[12]),这也有效。

2
我会说“构建”或“建立”(或者可能是“具体化”) - 因为你不是将生成器“转换”为列表,而是从数据源创建一个新的列表对象,该数据源恰好是一个生成器...(但我想这只是在挑刺,并且不确定我更喜欢哪种方式)。 - Jon Clements
2
我支持使用“构造函数”,因为它与其他面向对象语言保持一致。在其他语言中,list(arg)被理解为调用list类的构造函数。实际上,在Python中也是如此。关于对象是否在构造期间填充(如C++中的情况)或仅在第一个自动调用的方法(如Python的__init __()方法)中填充的争论不能改变基本的抽象概念。我的观点是列表构造函数接受迭代器并使用返回的值填充列表 - pepr
@pepr -- 是的,我同意。construct可能是最好的词。但要注意一点,不能保证__init__被调用。(来自__new__文档{http://docs.python.org/reference/datamodel.html#object.__new__})“如果__new__()不返回cls的实例,则新实例的__init__()方法将不会被调用。” - mgilson
3
为什么在jupyter notebook中会出现错误,而在shell中却可以正常运行?错误如下:'range' object is not callable。原因是在Jupyter Notebook中的某个代码单元中使用了名为range的变量或函数,导致Python解释器将其解析为一个范围对象(range object),而不是内置的range函数。然而,在shell中可能没有定义这样的变量或函数,所以代码可以正常工作。要解决这个问题,可以尝试使用其他名称来代替这个变量或函数。 - subtleseeker
我该如何将 np.nan 添加到这个列表中? - xarena
@subtleseeker:在笔记本中它运行得很好。你可能将某些内容分配给了 listrange - user2357112

54
在Python <= 3.4中,可以像其他人建议的那样使用list(range(10))来将范围(一般地,任何可迭代对象)转换为列表。
另一种选择是在Python 3.5中引入的,利用其解包广义化功能,在列表字面值[]中使用*
>>> r = range(10)
>>> l = [*r]
>>> print(l)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

虽然这与 list(r) 等价,但它是字面语法,没有涉及任何函数调用,因此可以更快地执行。如果你需要编写高效的代码,这也会更短。


8
要明确的是,您仍然可以将其一行化:[*range(10)]适用于当您不需要range以外的任何目的来初始化list的情况。 旁注:我最喜欢(好吧,不是真的)的展开概述的部分是空集现在具有文字语法,{*()},或者正如我所称之为单眼猴运算符。;-) - ShadowRanger
2
@ShadowRanger 这是我最初想写的方式。我决定更加详细地写,以免混淆新的Python用户 :-) - Dimitris Fasarakis Hilliard

26
在Python 3.x中,range()函数有自己的类型。因此,在这种情况下,您必须使用迭代器。 list(range(1000))

14
“在这种情况下,你必须使用迭代器”是什么意思?这到底是什么意思? - user2357112
2
我正在使用Python 3.7,尝试使用x=list(range(1000)),但出现了TypeError错误:“'list' object is not callable”。 - Earthshaker
@Earthshaker 你一定是打错了,应该是 list(range(1000))() - wjandrea

20

你真的不应该在列表中使用数字1-1000。但如果出于某些原因你确实需要这些数字,那么你可以这样做:

[i for i in range(1, 1001)]

简而言之,列表推导式:

上述列表推导式等同于:

nums = []
for i in range(1, 1001):
    nums.append(i)

这只是列表推导式的语法,来自2.x。我知道这在Python 3中有效,但不确定是否有升级的语法。

范围从第一个参数开始包含; 但在第二个参数(当提供2个参数时)之前结束,不包括第二个参数(如果省略第一个参数,则从'0'开始)

range(start, end+1)
[start, start+1, .., end]

24
为什么要理解?只需执行以下代码:list(range(1000)) - Rik Poggi
谢谢!您介意解释一下为什么是“i for i in…”而不是简单的“for i in…”吗? - Boathouse
我没有使用过Python3,所以对它的工作原理并不完全确定。我知道推导式可以工作,但对强制类型转换并不是100%确定。但如果强制类型转换可行,那么你是正确的,你的方法更符合Pythonic风格。 - inspectorG4dget
1
@inspectorG4dget: 这不是“转换类型”,而是使用可迭代对象调用list()构造函数。当给定任何可迭代对象时,list()构造函数知道如何创建一个新的列表。 - Greg Hewgill
4
@inspectorG4dget:在Python3中,list(range(1000))可以像在Python2中使用list(xrange(1000))一样工作。 - Rik Poggi
显示剩余3条评论

20
Python3 没有直接获取范围列表的函数是因为原本的 Python3 设计者在 Python2 中相当初学。他只考虑了在 for 循环中使用 range() 函数,因此,列表永远不需要扩展。实际上,我们经常需要使用 range() 函数生成一个列表并传递到函数中。
因此,在这种情况下,与 Python2 相比,Python3 较不方便,因为:
- 在 Python2 中,我们有 xrange() 和 range(); - 在 Python3 中,我们有 range() 和 list(range())
尽管如此,你仍然可以使用列表扩展的方式:
[*range(N)]

13
重点在于使创建列表变得不那么方便,因为通常这样做是错误的。对于99个使用情况中的99个,创建实际列表是低效且无意义的,因为range本身在几乎所有方面都像一个不可变序列,有时甚至更加高效(例如,对于int的包含测试是 O(1),而对于list则是O(n))。在Python 2中,人们倾向于默认使用range,即使xrange几乎总是更好的选择;在Python 3中,您必须明确选择list,而不能通过使用错误名称来无意中获得它。 - ShadowRanger
26
关于Python 3设计师及其在Python 2方面的专业知识的评论相当大胆和无礼。 - kazarey
@kazarey 但这是真的吗?在Python中有很多可疑的事情沿着这些线路。 - WestCoastProjects
Guido不是Python3的设计者吗?我找不到任何相反的证据。 - David Waterworth

13

Python 3:

my_list = [*range(1001)]

4

实际上,如果您想要1-1000(包括),请使用参数为1和1001的range(...)函数:range(1, 1001),因为range(start, end)函数从开始到(结束-1)。


0

在Python 3中,请使用Range

下面是一个示例函数,用于返回两个数字之间的数字

def get_between_numbers(a, b):
    """
    This function will return in between numbers from two numbers.
    :param a:
    :param b:
    :return:
    """
    x = []
    if b < a:
        x.extend(range(b, a))
        x.append(a)
    else:
        x.extend(range(a, b))
        x.append(b)

    return x

结果

print(get_between_numbers(5, 9))
print(get_between_numbers(9, 5))

[5, 6, 7, 8, 9]  
[5, 6, 7, 8, 9]

这似乎回答了一个不同的问题...? - wjandrea

-4
事实上,与Python2相比,这是Python3的倒退。当然,使用range()和xrange()的Python2比使用list(range())和range()的Python3更方便。原因是Python3的原始设计者经验不够丰富,他们只考虑了许多初学者使用range函数迭代大量元素时的内存和CPU效率问题,但忽略了使用range函数生成数字列表的情况。现在,他们已经无法回头了。
如果我是Python3的设计者,我会:
  1. 使用irange返回序列迭代器
  2. 使用lrange返回序列列表
  3. 使用range返回序列迭代器(如果元素数量很大,例如range(9999999))或序列列表(如果元素数量很小,例如range(10))
那应该是最优的。

这个回答如何解决问题? - wjandrea
是的,它通过请求Python3开发人员改进Python3来回答问题。但是由于它们不够优雅,所以他们不太可能进行更改。 - xuancong84

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接