代码之家  ›  专栏  ›  技术社区  ›  AndiDog

python:为什么不支持列表和元组之间的比较?

  •  19
  • AndiDog  · 技术社区  · 16 年前

    当比较一个元组和一个像…

    >>> [1,2,3] == (1,2,3)
    False
    >>> [1,2,3].__eq__((1,2,3))
    NotImplemented
    >>> (1,2,3).__eq__([1,2,3])
    NotImplemented
    

    …python不会像done那样深入比较它们 (1,2,3) == (1,2,3) .

    为什么会这样?是因为可变列表可以随时更改(线程安全问题)还是什么?

    (我知道CPython在哪里实现的,所以请不要回答 在哪里? 但是 为什么? 已实施。)

    2 回复  |  直到 16 年前
        1
  •  21
  •   Esteban Küber    16 年前

    你可以一直“铸造”它

    >>> tuple([1, 2]) == (1, 2)
    True
    

    记住,与JavaScript不同的是,python, is strongly typed 还有一些(大多数?)我们中的一些人喜欢这样。

        2
  •  9
  •   Chris B.    16 年前

    列表无法与元组进行比较没有技术上的原因;它完全是由语义驱动的设计决策。为了证明它与线程安全无关,可以将列表与其他列表进行比较:

    >>> l1 = [1, 2, 3]
    >>> l2 = [1, 2, 3]
    >>> l1 == l2
    True
    >>> id(l1) == id(l2)
    False
    

    允许用户直接比较列表和元组似乎是合理的,但最终会出现其他问题:是否应该允许用户比较列表和队列?有两个提供迭代器的对象吗?下面怎么办?

    >>> s = set([('x', 1), ('y', 2)])
    >>> d = dict(s)
    >>> s == d  # This doesn't work
    False
    

    很快就会变得复杂起来。语言设计者认识到了这个问题,并通过简单地防止不同的集合类型直接进行比较来避免这个问题。 1个 .

    请注意,这个简单的解决方案(从元组创建一个新的列表并对其进行比较)很容易,但效率很低。如果你处理的是大量的物品,你最好使用以下物品:

    def compare_sequences(iter1, iter2):
        iter1, iter2 = iter(iter1), iter(iter2)
        for i1 in iter1:
            try:
                i2 = next(iter2)
            except StopIteration:
                return False
    
            if i1 != i2:
                return False
    
        try:
            i2 = next(iter2)
        except StopIteration:
            return True
    
        return False
    

    这样做的好处是可以处理任意两个序列,而且成本很高。


    一 我注意到集合和冻结集合有一个例外。当然还有一些我不知道的人。语言设计师都是纯粹主义者,除了实际需要付出的代价。