为什么 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
。
它确实如您所想:创建一个从 0
到 9
的列表,然后删除元素 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
为什么
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
。
它确实如您所想:创建一个从 0
到 9
的列表,然后删除元素 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