【问题标题】:Improving Python list slicing改进 Python 列表切片
【发布时间】:2009-08-28 13:45:49
【问题描述】:

我想知道为什么 Python 的扩展/追加方法不返回对结果列表的引用。 要构建列表与最后一个元素的所有组合的字符串,我想写简单:

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)

如有错误请指正

【问题讨论】:

    标签: python list


    【解决方案1】:

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

    CQS 的深层动机并不是真正的“mutators 不应该返回任何有用的东西”:而是“查询应该没有副作用”。保持区别(无论是严格还是“作为准则而不是规则”)应该可以帮助您牢记这一点,并且在某种程度上确实有效(捕获一些意外错误),尽管有时会感到不便,如果你习惯了流畅流畅的“表达式和语句是同一件事”的语言。

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

    【讨论】:

      【解决方案2】:

      嗯,也许可以替换:

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

      与:

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

      【讨论】:

        【解决方案3】:

        一般的原因是None 中的返回类型表示list 正在就地修改。

        【讨论】:

        • 是的。我理解这一点,但问题是关于处理组合列表的更短的方法。在 c/c++ 中,我可以使用运算符 "," - 在计算结果之前执行多个操作。 Python 提供了什么?
        【解决方案4】:
        for i in range(l-1, 0, -1):
            yield ' '.join(src[:i] + src[-1:])
        

        会的。

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

        【讨论】:

        • 我认为有一个错误 - “+” 运算符加入两个列表,不会将元素附加到列表中。
        • 是的,在您发表评论之前已修复。
        • “for i in range(l, 0, -1):”是否应该以相反的顺序遍历 src 中的所有索引?这会更好:“for i in reversed(range(len(src))):” 它也会达到 0 索引。
        • 对不起。意思是在下面发表评论——它确实遵循了 OP 对我的问题的评论。
        【解决方案5】:

        要对列表进行操作然后返回,可以使用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
        

        【讨论】:

        • SilentGhost,请停止拖钓。我没有更改代码,我更改了我的 cmets,因为我做了一个 thinko。它说 X 必须始终为真,但我的意思是 X 必须始终为假(因为我们想返回 Y)。代码没有改变。
        • 代码更改了两次,从简单的代码行变为函数。从or xor li
        • 和? x -> li 是一个明显的错字。停止拖钓。这是一个完全符合提问者要求的答案。那值-1?
        猜你喜欢
        • 2017-06-24
        • 2015-02-19
        • 2014-05-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-27
        • 1970-01-01
        相关资源
        最近更新 更多