改进Python列表切片

时间:2009-08-28 13:45:50

标签: python list

我想知道为什么Python的extend / append方法不返回对结果列表的引用。 要使用last元素构建list的所有组合的字符串,我想写简单:

for i in range(l, 0, -1):
    yield " ".join(src[0:i-1].append(src[-1]))

但我得到了:TypeError。而是使用带有中间变量的代码:

 for i in range(l, 0, -1):
        sub = src[0:i-1]
        sub.append(src[-1])
        yield " ".join(sub)

如果我错了,请纠正我

5 个答案:

答案 0 :(得分:8)

Python中的变异方法没有返回对它们变异的对象的引用的原因可以在Command-Query Separation原则(简称CQS)中找到。 Python并不像Meyer的Eiffel语言那样彻底应用CQS(因为 - 根据Python的Zen,又名import this,“实用性胜过纯度”):例如,somelist.pop()确实返回了popped元素(仍然不是刚刚变异的容器;-),而在Eiffel中弹出一个堆栈没有返回值(在常见的情况下你需要弹出并使用top元素,你的第一个使用“查询”来偷看顶部,然后是一个“命令”让顶部消失。)

CQS的深层动机并非真正“变异者应该没有任何有用的东西”:相反,它是“查询应该没有副作用”。保持区别(无论是严格的还是“更多的指导而不是规则”)应该帮助你记住它,它确实在某种程度上起作用(捕捉一些偶然的错误),尽管它有时会感到不方便你已经习惯了流畅的“表达和陈述是一样的”语言。

Python中的CQS(广义上讲......)的另一个方面是语句和表达式之间的区别。同样,这并没有严格应用 - 表达式可以在语句可以使用的地方使用,偶尔会隐藏错误,例如当有人忘记调用他们需要foo()的函数时,不只是foo ;-)。但是,例如(并且与C,Perl等完全不同),在同一测试(if(a=foo())...)时,您无法轻松分配某些东西,这偶尔会带来不便,但会捕获其他类型的意外错误。

答案 1 :(得分:7)

嗯,也许替换:

src[0:i-1].append(src[-1])

使用:

src[0:i-1] + src[-1:] #note the trailing ":", we want a list not an element

答案 2 :(得分:1)

一般原因是None中的返回类型表明list正在被修改。

答案 3 :(得分:0)

for i in range(l-1, 0, -1):
    yield ' '.join(src[:i] + src[-1:])

会做的。

扩展/追加方法修改列表到位,因此不返回列表。

答案 4 :(得分:-1)

要对列表进行操作然后将其返回,您可以使用or构造:

def append_and_return(li, x):
  """silly example"""
  return (li.append(x) or li)

这里是X or Y评估X,如果X为真,则返回X,否则评估并返回Y. X需要始终为负。

但是,如果您只是在临时列表上操作,则已建议的串联操作也同样好或更好。

编辑:这不值钱

>>> li = [1, 2, 3]
>>> newli = append_and_return(li, 10)
>>> li
[1, 2, 3, 10]
>>> newli is li
True