La ragione fondamentale per cui id(reversed(a) == id(reversed(a)
rendimenti True
, mentre reversed(a) == reversed(a)
rendimenti False
, può essere visto da l'esempio di seguito utilizzando classi personalizzate -
>>> class CA:
... def __del__(self):
... print('deleted', self)
... def __init__(self):
... print('inited', self)
...
>>> CA() == CA()
inited <__main__.CA object at 0x021B8050>
inited <__main__.CA object at 0x021B8110>
deleted <__main__.CA object at 0x021B8050>
deleted <__main__.CA object at 0x021B8110>
False
>>> id(CA()) == id(CA())
inited <__main__.CA object at 0x021B80F0>
deleted <__main__.CA object at 0x021B80F0>
inited <__main__.CA object at 0x021B80F0>
deleted <__main__.CA object at 0x021B80F0>
True
Come si può vedere quando hai fatto customobject == customobject
, l'oggetto che è stato creato al volo non è stato distrutto fino a dopo la il confronto si è verificato, questo perché l'oggetto era richiesto per il confronto.
Ma in caso di id(co) == id(co)
, l'oggetto personalizzato creato è stato passato alla id()
funzione, e quindi solo il risultato di id
funzione è necessaria per il confronto, quindi l'oggetto creato ha alcun riferimento a sinistra, e quindi l'oggetto era raccolta dei rifiuti, e quindi quando l'interprete Python ha ricreato un nuovo oggetto per il lato destro dell'operazione ==
, ha riutilizzato lo spazio precedentemente liberato. Quindi, il id
per entrambi è venuto come lo stesso.
Questo comportamento sopra riportato è un dettaglio di implementazione di CPython (potrebbe/potrebbe non differire in altre implementazioni di Python). E non dovresti mai fare affidamento sull'eguaglianza di ids
. Ad esempio, nel caso di sotto di essa dà il risultato sbagliato -
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> id(reversed(a)) == id(reversed(b))
True
La ragione di questo è ancora una volta come spiegato sopra (garbage collection dell'oggetto reversed
creata per reversed(a)
prima della creazione dell'oggetto invertita per reversed(b)
).
Se le liste sono grandi, penso che il più efficiente della memoria e molto probabilmente il metodo più veloce per confrontare l'uguaglianza per due iteratori sarebbe quella di utilizzare all()
funzione built-in insieme a zip()
funzione per Python 3.x (oppure itertools.izip()
per Python 2.x).
Esempio Python 3.x -
all(x==y for x,y in zip(aiterator,biterator))
Esempio Python 2.x -
from itertools import izip
all(x==y for x,y in izip(aiterator,biterator))
Questo perché all()
cortocircuiti il primo valore False è incontri, e `zip () in Python 3.x restituisce un iteratore che restituisce gli elementi corrispondenti da entrambi i diversi iteratori. Questo non ha bisogno di creare un elenco separato in memoria.
Demo -
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> all(x==y for x,y in zip(reversed(a),reversed(b)))
False
>>> all(x==y for x,y in zip(reversed(a),reversed(a)))
True
Gli iteratori in genere si confrontano con False, perché non puoi sapere cosa otterrai dal passare sopra a loro fino a quando non lo fai. – jonrsharpe
Quindi il confronto restituisce False a causa dell'implementazione inversa di '__eq__'? – valignatev
'sorted' restituisce una lista. Un confronto più equo sarebbe tra 'iter (a)' e 'invertito (a)'. – wim