是否有文章或论坛讨论或其他某些内容解释了为什么列表使用append / extend但是sets和dicts使用add / update。
我经常发现自己将列表转换为集合,这种差异使得这非常繁琐,所以对于我的个人理智,我想知道合理化是什么。
在我们迭代开发时,需要定期进行转换。随着时间的推移,程序的结构会变形,各种结构会增加并失去排序和重复等要求。
例如,一些以列表中无序的东西开头的东西可能会提出没有重复的要求,因此需要转换为集合。
所有此类更改都需要查找并更改添加/附加和扩展/更新相关结构的所有位置。
所以我很想看到导致这种语言选择的原始讨论,不幸的是我没有用谷歌搜索它。
答案 0 :(得分:5)
append
有一个流行的定义“添加到最后”,extend
可以被类似地阅读(在细微差别中,它意味着“超出某一点”);集合没有“结束”,也没有任何方式在它们内部或“在它们的边界”指定一些“点”(因为没有“边界”!),因此建议可以执行这些操作将是非常误导的。
x.append(y)
总是将len(x)
增加一个(y
是否已列在列表x
中);对s.add(z)
没有这样的断言(s
的长度可能会增加或保持不变)。此外,在这些片段中,y
可以具有任何值(即,追加操作永远不会失败[除了您内存不足的异常情况]) - 再次没有关于z
的这种断言(必须是可清除的,否则add操作失败并引发异常)。类似的差异适用于extend
vs update
。对于具有如此截然不同的语义的操作使用相同的名称确实会非常误导。
使用列表似乎是pythonic 在第一关和处理 稍后迭代的表现
性能最差! list
支持重复项目,订购和任何项目类型 - set
s保证项目唯一性,没有订单概念,以及需求项目可持续性。 Pythonic没有使用列表(加上对副本等的愚蠢检查)代表一套 - 性能与否,“说出你的意思!”是Pythonic方式;-)。 (在诸如Fortran或C之类的语言中,作为内置容器类型的所有内容都是数组,如果您需要避免使用附加库,则可能必须执行此类“mental mapping”;在Python中,没有这样的需要)。
编辑:OP在评论中断言他们从一开始就不知道(例如)在某个算法中不允许重复(奇怪,但是,无论如何) - 他们是找到一个无痛的方法,一旦他们做发现重复的列表就很糟糕了(并且,我会补充:顺序无关紧要,项目可以删除,索引/切片不需要,等等)。为了获得完全相同的效果,如果Python的set
具有所讨论的两种方法的“同义词”:
class somewhatlistlikeset(set):
def append(self, x): self.add(x)
def extend(self, x): self.update(x)
当然,如果唯一的更改是在创建集合(以前是列表创建),那么代码可能更难以遵循,失去了使用add
vs {{1}的有用清晰度允许任何阅读代码的人知道“本地”对象是否是一个集合而不是列表...但这也是上述“完全相同的效果”的一部分! - )
答案 1 :(得分:3)
set
和dict
是无序的。 “追加”和“扩展”在概念上仅适用于有序类型。
答案 2 :(得分:1)
这是用来惹恼你的方式。
严重。它的设计使得一个不能简单地将一个转换为另一个。从历史上看,set
基于dict
,因此两者共享命名约定。虽然您可以轻松编写set
包装器来添加这些方法......
class ListlikeSet(set):
def append(self, x):
self.add(x)
def extend(self, xs):
self.update(xs)
...更大的问题是,为什么你会发现自己会如此规律地将list
转换为set
s。它们代表了一组对象的实质上不同的模型;如果你必须在两者之间进行很多转换,那么它表明你可能对你的程序的概念架构没有很好的处理。