2010-02-26 18 views
17

Quando si confrontano una tupla con una lista come ...Python: Perché il confronto tra liste e tuple non è supportato?

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

... Python non li profonda-compare come fatto con (1,2,3) == (1,2,3).

Quindi qual è la ragione di questo? È perché l'elenco mutabile può essere modificato in qualsiasi momento (problemi di sicurezza del thread) o cosa?

(io so dove questo è implementato in CPython, quindi per favore non rispondere dove, ma perché è implementato.)

+4

Una lista non è una tupla e viceversa. Sono diversi tipi. '[] ==()' restituirà 'False'. – jathanism

+0

Vedi anche: http://stackoverflow.com/questions/12135264/what-are-the-best-ways-to-compare-the-contents-oft-two-list-like-objects/12135322#12135322 – Erik

risposta

19

Puoi sempre "cast" è

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

Tenete presente che Python, a differenza ad esempio di Javascript, is stronglytyped, e alcuni (la maggior parte?) Di noi la preferiscono in questo modo.

+2

Che davvero è il modo migliore. – jathanism

+2

Mi piace pensare che la maggior parte di noi lo preferisca in questo modo. –

+0

Penso che l'idea della tipizzazione forte sia ciò che conta davvero qui, quindi accetterò la tua risposta come corretta. – AndiDog

7

Non esiste un motivo tecnico per gli elenchi che non possono essere confrontati con le tuple; è interamente una decisione di progettazione guidata dalla semantica. Per la prova che non è legato al filo di sicurezza, è possibile confrontare le liste ad altre liste:

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

Sembra ragionevole per consentire agli utenti di confrontare direttamente le liste e tuple, ma poi si finisce con altre domande: qualora il l'utente può confrontare liste e code? Che dire di due oggetti che forniscono gli iteratori? Che mi dici di quanto segue?

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

Può essere complicato abbastanza rapidamente. I progettisti di lingua hanno riconosciuto il problema e lo hanno evitato semplicemente impedendo a diversi tipi di raccolta di confrontare direttamente l'uno con l'altro .

Si noti che la soluzione semplice (creare una nuova lista dalla tupla e confrontarli) è semplice ma inefficiente. Se si sta lavorando con un gran numero di elementi, è sta meglio con qualcosa di simile:

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 

Questo ha il vantaggio di lavorare su qualsiasi due sequenze, ad un costo evidente complessità.


rilevo c'è una deroga per i set e frozensets. E senza dubbio alcuni altri di cui non sono a conoscenza. I progettisti di linguaggi sono puristi, eccetto dove vale la pena di essere pratico.

+0

+1 Ottimi punti, grazie! – AndiDog

+3

Per confrontare due sequenze, non è necessario passare attraverso i cerchi Next/StopIteration. all (i1 == i2 per i1, i2 in itertools.izip_longest (iter1, iter2, fillvalue = object())) –

Problemi correlati