Основная причина, почему id(reversed(a) == id(reversed(a)
возвращает True
, в то время как reversed(a) == reversed(a)
возвращается False
, можно видеть из приведенного ниже примера, используя пользовательские классы -
>>> 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
Как вы можете видеть, когда вы сделали customobject == customobject
объект, который был создан на лету не был разрушен до после сравнение произошло, это потому, что этот объект был необходим для сравнения.
Но в случае id(co) == id(co)
, пользовательский объект, созданный был передан id()
функции, а затем только результат id
функции требуется для сравнения, так что объект, который был создан не имеет никаких ссылок слева, и, следовательно, объект был сбор мусора, а затем, когда интерпретатор Python воссоздал новый объект для правой стороны операции ==
, он снова использовал освобожденное пространство. Следовательно, id
для обоих были такими же.
Данное поведение является частью реализации CPython (она может/не может отличаться в других реализациях Python). И вы никогда не должны полагаться на равенство ids
. Например, в случае ниже дает неправильный результат -
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> id(reversed(a)) == id(reversed(b))
True
Причина этого опять-таки, как описано выше (вывоз мусора из reversed
объекта, созданного для reversed(a)
до создания реверсивного объекта для reversed(b)
).
Если списки большие, я думаю, что самая память эффективная и наиболее вероятно, самый быстрый способ для сравнения равенства двух итераторов была бы использовать all()
встроенной функции наряду с zip()
функции для Python 3.x (или itertools.izip()
для Python 2.x).
Пример для Python 3.x -
all(x==y for x,y in zip(aiterator,biterator))
Пример для Python 2.x -
from itertools import izip
all(x==y for x,y in izip(aiterator,biterator))
Это происходит потому, all()
коротких замыкания на первое ложного значения является столкновением, и `молнии () в Python 3.x возвращает итератор, который выдает соответствующие элементы из разных итераторов. Это не нужно создавать отдельный список в памяти.
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
Итераторы обычно сравниваются как False, потому что вы не можете знать, что вы получите от итерации над ними, пока вы это сделаете. – jonrsharpe
Итак, сравнение возвращает False из-за обратной реализации '__eq__'? – valignatev
'sorted' возвращает список. Более справедливое сравнение было бы между «iter (a)» и «обратным (a)». – wim