我想知道为什么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)
如果我错了,请纠正我
答案 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