2010-02-26 15 views
17

Al comparar una tupla con una lista como ...Python: ¿Por qué no se admite la comparación entre listas y tuplas?

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

... Python no profunda comparémoslas como se ha hecho con (1,2,3) == (1,2,3).

¿Cuál es la razón de esto? ¿Es porque la lista mutable se puede cambiar en cualquier momento (problemas de seguridad de los hilos) o qué?

(sé que esto se implementa en CPython, así que por favor no conteste donde, pero por qué se aplica.)

+4

Una lista no es una tupla y viceversa. Son diferentes tipos. '[] ==()' devolverá 'False'. – jathanism

+0

Vea también: http://stackoverflow.com/questions/12135264/what-are-the-best-ways-to-compare-the-contents-of-two-list-like-objects/12135322#12135322 – Erik

Respuesta

19

Puede siempre "fundido" que

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

Tenga en cuenta que Python, a diferencia de, por ejemplo, Javascript, is stronglytyped, y algunos (¿la mayoría?) De nosotros lo preferimos de esa manera.

+2

Eso realmente Es la mejor manera. – jathanism

+2

Me gusta pensar que la mayoría de nosotros lo prefiere de esa manera. –

+0

Creo que la idea de escribir fuerte es lo que realmente importa aquí, así que aceptaré su respuesta como correcta. – AndiDog

7

No hay ninguna razón técnica para que las listas no puedan compararse con las tuplas; es totalmente una decisión de diseño impulsada por la semántica. Como prueba de que no está relacionado con el hilo de seguridad, se puede comparar la lista a otras listas:

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

Parece razonable que los usuarios puedan comparar directamente las listas y tuplas, pero luego terminar con otra pregunta: si el el usuario puede comparar listas y colas? ¿Qué pasa con dos objetos que proporcionan iteradores? ¿Qué hay de lo siguiente?

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

Se puede complicar bastante rápido. Los diseñadores de idiomas reconocieron el problema y lo evitaron simplemente impidiendo que diferentes tipos de colecciones se compararan directamente entre sí .

Tenga en cuenta que la solución simple (para crear una nueva lista de la tupla y compararlos) es fácil pero ineficiente. Si está trabajando con un gran número de artículos, usted está mejor con algo como:

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 

Esto tiene la ventaja de trabajar en cualquiera de las dos secuencias, a un costo obvio en complejidad.


observo que hay una excepción para los conjuntos y frozensets. Y sin duda algunos otros que no conozco. Los diseñadores de idiomas son puristas, excepto donde vale la pena ser prácticos.

+0

+1 Muy buenos puntos, gracias! – AndiDog

+3

Para comparar dos secuencias, no hay necesidad de saltar a través de los aros next/StopIteration. all (i1 == i2 para i1, i2 en itertools.izip_longest (iter1, iter2, fillvalue = object())) –

Cuestiones relacionadas