L'union de 2 ensembles ne contient pas tous les éléments

94

Comment se fait-il que lorsque je change l'ordre des deux ensembles dans les unions ci-dessous, j'obtiens des résultats différents?

set1 = {1, 2, 3}
set2 = {True, False}

print(set1 | set2)
# {False, 1, 2, 3}

print(set2 | set1)
#{False, True, 2, 3}
Blueplastic
la source

Réponses:

110

Pourquoi l'union () ne contient pas tous les éléments

Les 1et Truesont équivalents et considérés comme des doublons. De même, 0et Falsesont également équivalents:

>>> 1 == True
True
>>> 0 == False
True

Quelle valeur équivalente est utilisée

Lorsque plusieurs valeurs équivalentes sont rencontrées, les ensembles conservent la première vue:

>>> {0, False}
{0}
>>> {False, 0}
{False}

Façons de différencier les valeurs

Pour les faire traiter comme distincts, stockez-les simplement par (value, type)paire:

>>> set1 = {(1, int), (2, int), (3, int)}
>>> set2 = {(True, bool), (False, bool)}
>>> set1 | set2
{(3, <class 'int'>), (1, <class 'int'>), (2, <class 'int'>),
 (True, <class 'bool'>), (False, <class 'bool'>)}
>>> set1 & set2
set()

Une autre façon de différencier les valeurs consiste à les stocker sous forme de chaînes:

>>> set1 = {'1', '2', '3'}
>>> set2 = {'True', 'False'}
>>> set1 | set2
{'2', '3', 'False', 'True', '1'}
>>> set1 & set2
set()

J'espère que cela clarifie le mystère et montre la voie à suivre :-)


Sauvé des commentaires:

Il s'agit de la technique standard pour rompre l'équivalence de type croisé (c. 0.0 == 0-à- d . True == 1, EtDecimal(8.5) == 8.5) . La technique est utilisée dans le module d'expression régulière de Python 2.7 pour forcer les expressions régulières Unicode à être mises en cache distinctement des expressions rationnelles str équivalentes. La technique est également utilisée en Python 3 pour functools.lru_cache () lorsque le paramètre tapé est vrai.

Si l'OP a besoin d'autre chose que la relation d'équivalence par défaut, une nouvelle relation doit être définie. Selon le cas d'utilisation, cela peut être une insensibilité à la casse pour les chaînes, la normalisation pour unicode, l'apparence visuelle (les choses qui semblent différentes sont considérées comme différentes), l'identité (aucun objet distinct n'est considéré comme égal), une paire valeur / type, ou quelque autre fonction qui définit une relation d'équivalence. Compte tenu de l'exemple spécifique des OP, il semblerait qu'il s'attendait à une distinction par type ou à une distinction visuelle.

Raymond Hettinger
la source
20

En Python, Falseet 0sont considérés comme équivalents, tout comme Trueet 1. Parce que Trueet 1sont considérés comme la même valeur, un seul d'entre eux peut être présent dans un ensemble à la même heure. Lequel dépend de l'ordre dans lequel ils sont ajoutés à l'ensemble. Dans la première ligne, set1est utilisé comme premier ensemble, nous obtenons donc 1dans l'ensemble résultant. Dans le deuxième ensemble, Trueest dans le premier ensemble, donc Trueest inclus dans le résultat.

mcslane
la source
6

Si vous regardez https://docs.python.org/3/library/stdtypes.html#boolean-values section 4.12.10. Valeurs booléennes:

Les valeurs booléennes sont les deux objets constants False et True . Ils sont utilisés pour représenter des valeurs de vérité (bien que d'autres valeurs puissent également être considérées comme fausses ou vraies). Dans les contextes numériques (par exemple lorsqu'ils sont utilisés comme argument d'un opérateur arithmétique), ils se comportent comme les entiers 0 et 1 , respectivement.

chocksaway
la source
4

L'opérateur de comparaison ( ==, !=) est défini pour booléen Trueet Falsepour correspondre à 1 et 0.

C'est pourquoi, dans l'union des ensembles, lorsqu'il vérifie s'il se Truetrouve déjà dans le nouvel ensemble, il obtient une réponse véridique:

>>> True in {1}
True
>>> 1 in {True}
True
Uriel
la source