Zestawy test równości i dopóki istnieją nowe wersje Pythona, kolejność, w jakiej robią to może się różnić w zależności na formularzu podajesz wartości zestawowi, który budujesz, co pokażę poniżej.
Od 0 == x
prawda i0 == y
to prawda, ale x == y
jest fałszywe zachowanie tutaj jest naprawdę niezdefiniowany, ponieważ zakłada się, że zestaw x == y
muszą być prawdziwe, jeśli dwa pierwsze testy były zbyt prawdziwe.
Jeśli odwrócić wykazu przekazanego do set()
, a następnie pojawi się taki sam efekt jak użycie dosłownym, ponieważ kolejność równości testuje zmiany:
>>> set([y, x, 0])
set([0j, Decimal('0')])
i taka sama dla odwrócenia dosłowne:
>>> {y, x, 0}
set([0])
co się dzieje jest to, że zestaw dosłowne wartości obciążenia na stosie, a następnie stos wartości są dodawane do nowego zestawu obiektów w odwrotnej kolejności.
Dopóki 0
załadowano pierwszy, dwa inne cele są następnie testowane na 0
już w zestawie. W chwili, jeden z dwóch innych obiektów jest ładowany pierwszy test równości nie i masz dwa obiekty dodania:
>>> {y, 0, x}
set([Decimal('0'), 0j])
>>> {x, 0, y}
set([0j, Decimal('0')])
To ustawienie literały dodać elementy w odwrotnej kolejności jest obecny błąd we wszystkich wersjach Pythona, które obsługują składnię , aż do wersji Python 2.7.12 i 3.5.2. Zostało ono ostatnio naprawione, patrz issue 26020 (część 2.7.13, 3.5.3 i 3.6, z których żadna nie została jeszcze wydana). Jeśli spojrzeć na 2.7.12, można zobaczyć, że BUILD_SET
in ceval.c
odczytuje stos od góry do dołu:
# oparg is the number of elements to take from the stack to add
for (; --oparg >= 0;) {
w = POP();
if (err == 0)
err = PySet_Add(x, w);
Py_DECREF(w);
}
natomiast kod bajtowy dodaje elementy na stosie w kolejności odwrotnej (popychanie 0
na stosie pierwszy):
>>> from dis import dis
>>> dis(compile('{0, x, y}', '', 'eval'))
2 0 LOAD_CONST 1 (0)
3 LOAD_GLOBAL 0 (x)
6 LOAD_GLOBAL 1 (y)
9 BUILD_SET 3
12 RETURN_VALUE
Poprawka polega na odczytaniu elementów ze stosu w odwrotnej kolejności; Python 2.7.13 version wykorzystuje PEEK()
zamiast POP()
(i STACKADJ()
usunąć elementy ze stosu potem):
for (i = oparg; i > 0; i--) {
w = PEEK(i);
if (err == 0)
err = PySet_Add(x, w);
Py_DECREF(w);
}
STACKADJ(-oparg);
testowania równości problem ma tę samą przyczynę jak inne pytanie; Klasa Decimal()
ma problemy z równą wersją z complex
tutaj, która została naprawiona w Pythonie 3.2 (przez utworzenie Decimal()
support comparisons to complex
and a few other numeric types it didn't support before).
pokrewne: [Dict/Set analizowaniem Zamówienie Spójność] (https://stackoverflow.com/q/34623846/4279) – jfs