附加范围功能

时间:2013-11-16 12:59:56

标签: python python-2.x

编辑:感谢您对如何完成我想要做的事情的回复,但问题是为什么范围()。append()返回如果你一步完成就没有,如果你两步完成,那么<​​em>为什么它是有效的。

我试图创建一个数字列表,但有一个扭曲。我不希望在列表的开头有几个数字:

mlist = [0, 5, 6, 7, ...]

所以我想做以下事情:

 mlist = range(5,n+1).append(0)

但默默失败,因为type(mlist)之后等于NoneType? (相关:type(range(5,10)评估为list类型)

如果我尝试分两步完成,例如:

>>> mlist = range(5,10)
#and then
>>> mlist.append(0)
>>> mlist
[5, 6, 7, 8, 9, 10, 0]

发生了什么事?

3 个答案:

答案 0 :(得分:6)

list.append()改变列表到位,然后返回None。通过将您指定的返回值分配给mlist,而不是您要构建的列表。这是一个标准的Python习语;改变可变对象的方法永远不会返回已更改的对象,始终为None

分开两个步骤:

mlist = range(5, n + 1)
mlist.append(0)

这会将[0]添加到结尾;如果您在开始时需要0,请使用:

mlist = [0] + range(5, n + 1)

或者您可以再次使用list.insert()作为单独的电话:

mlist = range(5, n + 1)
mlist.insert(0, 0)

但是后者必须将所有元素向上移动一步,并且通过连接创建新列表是更短的列表的更快选项,更长列表上的插入获胜:

>>> from timeit import timeit
>>> def concat(n):
...     mlist = [0] + range(5, n)
... 
>>> def insert(n):
...     mlist = range(5, n)
...     mlist.insert(0, 0)
... 
>>> timeit('concat(10)', 'from __main__ import concat')
1.2668070793151855
>>> timeit('insert(10)', 'from __main__ import insert')
1.4820878505706787
>>> timeit('concat(1000)', 'from __main__ import concat')
23.53221583366394
>>> timeit('insert(1000)', 'from __main__ import insert')
15.84601092338562

答案 1 :(得分:4)

有多种选择,但最简单的可能是:

>>> mlist = [0] + range(5,10)
>>> mlist
[0, 5, 6, 7, 8, 9]

要在开头插入项目,请将list.insert0(索引0)一起使用:

>>> mlist = range(5,10)
>>> mlist.insert(0, 0) # the first 0: index, the second 0: the item to insert
>>> mlist
[0, 5, 6, 7, 8, 9]

回答编辑

大多数改变序列/ maping的方法返回None。所以只需调用方法,不要将返回值重新分配给变量。

请参阅Python常见问题解答中的Why doesn’t list.sort() return the sorted list?

答案 2 :(得分:4)

  编辑:感谢您对如何完成我想要做的事情的回复,但问题是关于WHY范围()。如果您在一个步骤中尝试,则append()将返回None,以及为什么它会起作用你有两步这个程序。

简单地说 - GvR不喜欢它 - 来自Python developers mailing list

  

我想再次解释为什么我如此坚定,以至于sort()不应该   回归'自我'。

     

这来自编码风格(在各种其他语言中流行,我   相信特别是Lisp狂热其中的一系列副作用   在单个对象上可以链接如下:

     

x.compress()。斩(Y)的.sort(z)的

     

相同      

x.compress()
x.chop(y)
x.sort(z)

     

我发现链接形式对可读性构成威胁;它需要的   读者必须非常熟悉每种方法。该   第二种形式清楚地表明这些调用中的每一个都是相同的   对象,所以即使你不了解类及其方法   好吧,你可以理解第二次和第三次调用都适用于   x(并且所有调用都是针对它们的副作用而制作的),而不是   别的什么。

     

我想为返回新值的操作保留链接,   像字符串处理操作:

     

y = x.rstrip(“\ n”)。split(“:”)。lower()

     

有一些标准库模块可以鼓励链接   副作用电话(pstat浮现在脑海中)。不应该有任何新的   那些;当它很弱时,pstat穿过我的过滤器。