为什么 range(0,10).remove(1) 不起作用?

why range(0,10).remove(1) does not work?

为什么

range(0,10).remove(1)

不起作用?

我知道这个问题很短,但我不知道为什么这个东西不起作用.. 可以写成一行吗?

因为 remove() 方法运行 "in place",而不 return 任何东西。

x = range(0, 10) 将 return 列表或 range 对象(取决于您的 Python 版本)。

Python 2.x

x = range(0, 10).remove(1) 将 return None 因为 list.remove 将修改列表 就地 等 returns None。您的列表已创建并删除了值 1,但由于它从未分配给任何东西,因此被垃圾收集。

Python 3.x

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

获得所需内容的一种方法是使用 list comprehension。在列表理解中,您将遍历 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]

问题在于 remove 是就地操作,因此 returns None

它确实如您所想:创建一个从 09 的列表,然后删除元素 1,但这是一个临时列表,不是分配给任何变量。

作为替代方案,列表理解可以实现这一点

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

为什么 remove 不起作用已经介绍过了。 我想介绍 list comprehension 方法的替代方法:

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

虽然列表推导式被认为更像 pythonic,但 filter 有时可能更接近于表达潜在的问题。

结果是 None 因为 list.remove() 没有 return 任何东西。您可以使用 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