Python中add()、append()、update()和extend()的用法

6
有没有一篇文章或论坛讨论或其他东西解释为什么列表使用append / extend,而集合和字典使用add / update?
我经常发现自己将列表转换为集合,这种差异使得这项工作变得相当繁琐,因此出于个人的精神健康,我希望知道背后的理由。
在开发中,需要在不同结构之间进行转换。随着程序结构的改变,各种结构会获得和失去如排序和重复等要求。
例如,开始作为无序的一堆东西的列表可能会收到无重复项的要求,因此需要转换为集合。
所有这些更改都需要查找并更改添加/追加和扩展/更新相关结构的所有位置。
因此,我很想看看最初的讨论是什么,导致了这种语言选择,但不幸的是我在谷歌上没有找到任何有用信息。
3个回答

6
append通常被定义为“添加到最后”,而extend也可以类似地阅读(在它的意思是“......超出某个点”的细微差别中); 集合没有“结尾”,也没有任何方法指定其中的某个“点”或“在其边界处”(因为没有“边界”!),因此建议执行这些操作会非常误导。

x.append(y)始终将len(x)增加一(无论y是否已经在列表x中); 对于s.add(z)没有这样的断言(s的长度可能会增加或保持不变)。 此外,在这些代码片段中,y可以具有任何值(即,追加操作从不失败[除了您已经耗尽内存的异常情况]) - 再次没有关于z的这样的断言(它必须是可散列的,否则添加操作会失败并引发异常)。extendupdate之间存在类似的差异。使用具有如此不同语义的操作相同的名称将非常误导。

似乎在第一遍通过时只使用列表很符合Python风格,并在以后的迭代中处理性能

性能是最不重要的!list支持重复项,排序和任何项目类型 - set保证项目唯一性,没有排序概念,并且要求项目可散列。使用列表(加上针对重复项等的古怪检查)来表示集合-无论是否有性能问题,“说出你的意思!”才是Pythonic Way;-)。(在诸如Fortran或C之类的语言中,如果需要避免使用附加库,则可能必须执行此类“心理映射”; 在Python中,不存在这种需要)。

编辑:OP在评论中断言他们不知道从一开始就禁止重复项(奇怪,但是,无所谓) - 他们正在寻找一种轻松的方法将列表转换为集合,一旦他们发现重复项在那里是不好的(而且,我会补充说:顺序无关紧要,项目是可散列的,不需要索引/切片等)。为了获得与Python的set具有两种相关方法的“同义词”完全相同的效果:

class somewhatlistlikeset(set):
    def append(self, x): self.add(x)
    def extend(self, x): self.update(x)

当然,如果唯一的变化在于集合创建(曾经是列表创建),那么代码可能更加难以理解,因为失去了使用addappend区分对象是集合还是列表的有用清晰性... 但这也是上述“完全相同效果”的一部分!-)

我在哪里暗示我在使用“愚蠢的检查”来检测重复项?将列表转换为集合的一个主要例子是需要确保它没有重复项。当然,这意味着我必须找到并更改所有涉及它的代码。实际上,现在你建议了这个方法,添加愚蠢的检查比查找所有的追加和扩展要容易得多。 - Gordon Wrigley
@tolomea,我默认你已经知道算法中是否可能出现重复。你很可能需要找到所有的添加和扩展操作(如果列表在长度检查等中间用到)以避免追加重复或有选择性地进行扩展。当然,也可以使用集合子类并增加一些内容——让我编辑一下A来展示这一点。 - Alex Martelli

3

setdict 是无序的。 "Append" 和 "extend" 的概念只适用于有序类型。


我相当确定,当你说“add”时,你的意思是“追加(append)”。 - Gordon Wrigley

2

这么写是为了让你不舒服。

说真的,它的设计是为了使得两者不能轻易地相互转换。历史上,set是基于dict构建的,因此两者共享命名约定。虽然你可以很容易地编写一个set包装器来添加这些方法……

class ListlikeSet(set):
    def append(self, x):
        self.add(x)

    def extend(self, xs):
        self.update(xs)

...更大的问题是,为什么你经常需要将 list 转换为 set。它们代表着一个集合对象的不同模型;如果你经常在两者之间进行转换,说明你可能对程序的概念架构掌握得不是很好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接