代码之家  ›  专栏  ›  技术社区  ›  Björn Pollex

为什么集合不能在Python中统一处理?

  •  6
  • Björn Pollex  · 技术社区  · 14 年前

    集合和列表在Python中的处理方式不同,似乎没有统一的方式来处理这两种情况。例如,将项添加到 set 使用 add 方法,以及 list 使用 append 方法。我知道这背后有不同的语义,但这里也有共同的语义,通常与一些集合一起工作的算法更关心共性而不是差异。C++ STL表明这是可行的,那么为什么Python中没有这样的概念呢?

    编辑: 在C++中,我可以使用 output_iterator 将值存储在(几乎)任意类型的集合中,包括列表和集合。我可以编写一个以这样的迭代器为参数并向其写入元素的算法。然后,该算法对支持迭代器的容器类型(或者其他设备,可能是文件)是完全不可知的。如果支持容器是一个忽略重复项的集合,那么这是调用方的决定。我的具体问题是,它已经发生了好几次,现在我使用的例子是 列表 为了完成某项任务,后来决定 设置 更合适。现在我必须改变 追加 添加 在我的代码中有几个地方。我只是想知道为什么python对这种情况没有概念。

    3 回复  |  直到 11 年前
        1
  •  6
  •   Glenn Maynard    14 年前

    直接的答案是:这是一个设计缺陷。

    您应该能够用相同的方法名插入到任何有意义的通用插入(例如,不包括dict)容器中。插入应该有一个一致的通用名称,例如。 add ,对应于 set.add list.append ,这样就可以添加到容器中,而不必太在意要插入的内容。

    在不同类型中为此操作使用不同的名称是一种毫无意义的不一致性,并且设置了一个糟糕的基本标准:库应该鼓励用户容器使用一致的API,而不是为每个基本容器提供基本上不兼容的API。

    也就是说,在这种情况下,这通常不是一个实际问题:大多数情况下,当函数的结果是一个项目列表时,将其作为生成器实现。它们允许一致地处理这两种情况(从函数的角度),以及其他形式的迭代:

    def foo():
        yield 1
        yield 2
        yield 3
    
    s = set(foo())
    l = list(foo())
    results1 = [i*2 for i in foo()]
    results2 = (i*2 for i in foo())
    for r in foo():
        print r
    
        2
  •  4
  •   Ivo van der Wijk    14 年前

    添加和追加 不同的。集合是无序的,包含唯一的元素,而append则建议始终添加该项,并在末尾专门完成这一操作。

    集合和列表都可以被视为iterables,这是它们的通用语义,并且可以由您的算法自由使用。

    如果您的算法依赖于某种加法,那么您就不能简单地依赖于具有相同行为的集合、元组、列表、dict和字符串。

        3
  •  1
  •   Kenan Banks    14 年前

    实际原因可能与Python历史有关。

    内置的集合类型不是 built-in until Python 2.6 ,它基于一个sets模块,在python 2.3之前,这个模块本身不在标准库中。显然,更改集合类型的语义可能会破坏依赖于原始集合模块的大量现有代码,而且通常语言设计人员避免在没有主要数字发布的情况下破坏现有代码。

    如果愿意的话,您可以责怪最初的模块作者,但请记住,在python 2.2之前,用户定义的类型和内置类型必须存在于不同的宇宙中,这意味着您不能直接扩展内置类型,并且可能允许模块作者对不维护一致的集合语义感到满意。