为什么range(0,10).remove(1)无法工作?

6

为什么

range(0,10).remove(1)

不能工作?

我知道这个问题非常简短,但我不知道为什么这个东西不能工作... 是否可能将其写成一行?

5个回答

12

x = range(0, 10)将返回一个列表或range对象(取决于Python版本)。

Python 2.x

x = range(0, 10).remove(1)会返回None,因为list.remove会直接修改列表,因此返回None。虽然已经创建了列表并删除了值1,但由于没有分配给任何变量,所以它被垃圾回收了。

Python 3.x

x = range(0, 10).remove(1)会返回AttributeError,因为range对象没有remove方法。如果使用list(range(0, 10)).remove(1)将其转换为列表,则会遇到与Python 2相同的问题。

实现想要的效果的一种方法是使用列表推导式。在列表推导式中,您可以遍历range(0, 10),但使用if语句仅添加不为1的值,例如:

x = [i for i in range(0, 10) if i != 1]
# [0, 2, 3, 4, 5, 6, 7, 8, 9]

最好使用Python 2中的[i for i in xrange(0, 10) if i != 1] - martineau

2
由于remove()方法是"就地"执行的,不会返回任何内容。

1
问题在于remove是一种就地操作,因此返回None。 它确实会执行你认为的操作:创建一个从09的列表,然后删除元素1,但这是一个临时列表,没有分配给任何变量。 作为替代方案,可以使用列表推导式来实现。
>>> [i for i in range(0,10) if i != 1]
[0, 2, 3, 4, 5, 6, 7, 8, 9]

0

为什么remove不起作用已经讨论过了。 我想提供一种替代列表推导式方法的方案:

In [1]: filter(lambda x:x!=1, range(10))
Out[1]: [0, 2, 3, 4, 5, 6, 7, 8, 9]

虽然列表推导式被认为更具Python风格,但filter有时可能更接近于表达底层问题。


0

结果是None,因为list.remove()不返回任何内容。您可以通过使用lambda函数和or运算符来解决这个问题。

在Python 2中,这个一行代码就可以解决:

(lambda lst=range(0, 10): lst.remove(1) or lst)()

或者在Python 3中这样写:

(lambda lst=list(range(0, 10)): lst.remove(1) or lst)()

两者的执行速度都比使用列表推导式要快(尽管它不太易读):

> python -mtimeit "(lambda lst=range(0, 10): lst.remove(1) or lst)()"
1000000 loops, best of 3: 0.467 usec per loop

> python -mtimeit "[i for i in range(0, 10) if i != 1]"
1000000 loops, best of 3: 0.815 usec per loop

> c:\python3\python -mtimeit "(lambda lst=list(range(0, 10)): lst.remove(1) or lst)()"
1000000 loops, best of 3: 0.817 usec per loop

> c:\python3\python -mtimeit "[i for i in range(0, 10) if i != 1]"
1000000 loops, best of 3: 1.17 usec per loop

为什么需要或运算符? - JFFIGK
@JFFIGK:这是必需的,以便表达式的结果将是(更新后的)lst。它之所以有效,是因为Python的or运算符的工作方式。 - martineau

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