我经常发现自己将列表转换为集合,这种差异使得这项工作变得相当繁琐,因此出于个人的精神健康,我希望知道背后的理由。
在开发中,需要在不同结构之间进行转换。随着程序结构的改变,各种结构会获得和失去如排序和重复等要求。
例如,开始作为无序的一堆东西的列表可能会收到无重复项的要求,因此需要转换为集合。
所有这些更改都需要查找并更改添加/追加和扩展/更新相关结构的所有位置。
因此,我很想看看最初的讨论是什么,导致了这种语言选择,但不幸的是我在谷歌上没有找到任何有用信息。
append
通常被定义为“添加到最后”,而extend
也可以类似地阅读(在它的意思是“......超出某个点”的细微差别中); 集合没有“结尾”,也没有任何方法指定其中的某个“点”或“在其边界处”(因为没有“边界”!),因此建议执行这些操作会非常误导。
x.append(y)
始终将len(x)
增加一(无论y
是否已经在列表x
中); 对于s.add(z)
没有这样的断言(s
的长度可能会增加或保持不变)。 此外,在这些代码片段中,y
可以具有任何值(即,追加操作从不失败[除了您已经耗尽内存的异常情况]) - 再次没有关于z
的这样的断言(它必须是可散列的,否则添加操作会失败并引发异常)。extend
与update
之间存在类似的差异。使用具有如此不同语义的操作相同的名称将非常误导。
似乎在第一遍通过时只使用列表很符合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)
add
与append
区分对象是集合还是列表的有用清晰性... 但这也是上述“完全相同效果”的一部分!-)set
和 dict
是无序的。 "Append" 和 "extend" 的概念只适用于有序类型。
这么写是为了让你不舒服。
说真的,它的设计是为了使得两者不能轻易地相互转换。历史上,set是基于dict构建的,因此两者共享命名约定。虽然你可以很容易地编写一个set包装器来添加这些方法……
class ListlikeSet(set):
def append(self, x):
self.add(x)
def extend(self, xs):
self.update(xs)
...更大的问题是,为什么你经常需要将 list
转换为 set
。它们代表着一个集合对象的不同模型;如果你经常在两者之间进行转换,说明你可能对程序的概念架构掌握得不是很好。