Jeux de test pour l'égalité, et jusqu'à ce qu'il y a de nouvelles versions de Python, l'ordre dans lequel ils le font peut varier en fonction de la forme de la main, les valeurs de l'ensemble en cours de construction, je vais montrer ci-dessous.
Depuis 0 == x
est vrai et 0 == y
est vrai, mais x == y
est faux, le comportement ici, c'est vraiment pas défini, comme l'ensemble suppose qu' x == y
doit être vrai si les deux premiers tests ont été aussi vrai.
Si vous inversez la liste transmise à l' set()
, puis vous obtenez le même résultat que l'utilisation d'un littéral, parce que l'ordre des tests d'égalité des changements:
>>> set([y, x, 0])
set([0j, Decimal('0')])
et de même pour inverser le sens littéral:
>>> {y, x, 0}
set([0])
Ce qui se passe est que l'ensemble littérale charge les valeurs sur la pile, puis la pile de valeurs sont ajoutées à la nouvelle série de l'objet dans l'ordre inverse.
Tant que 0
est chargé en premier, les deux autres objets sont ensuite testés contre 0
déjà dans le jeu. Le moment où l'un de l'autre deux objets est chargé en premier, l'égalité test échoue, et vous obtenez deux objets ajoutés:
>>> {y, 0, x}
set([Decimal('0'), 0j])
>>> {x, 0, y}
set([0j, Decimal('0')])
Que l'ensemble des littéraux ajouter des éléments dans le sens inverse est un bug présent dans toutes les versions de Python qui prennent en charge la syntaxe, tout le chemin jusqu'à ce que Python 2.7.12 et 3.5.2. Il a été récemment résolu, voir question 26020 (partie de 2.7.13, 3.5.3 et 3.6, aucun n'a encore été dévoilé). Si vous regardez 2.7.12, vous pouvez voir qu' BUILD_SET
en ceval.c
lit la pile de haut en bas:
# 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);
}
alors que le bytecode ajoute des éléments de la pile dans l'ordre inverse (en appuyant 0
sur la pile en premier):
>>> 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
La solution est de lire les éléments de la pile dans l'ordre inverse; le Python 2.7.13 version utilise PEEK()
au lieu de POP()
(et un STACKADJ()
supprimer les éléments de la pile par la suite):
for (i = oparg; i > 0; i--) {
w = PEEK(i);
if (err == 0)
err = PySet_Add(x, w);
Py_DECREF(w);
}
STACKADJ(-oparg);
L'égalité d'essais problème a la même cause que l'autre question; l' Decimal()
classe est d'avoir quelques questions d'égalité avec complex
ici, qui a été fixé en Python 3.2 ( Decimal()
soutien des comparaisons complex
et quelques autres types numériques, il n'était pas avant).