La raison pour laquelle vous perdez les valeurs booléennes d'une set
s'ils contiennent déjà 0
o 1
c'est parce que le comportement suivant...
>>> hash(1) == hash(True)
True
>>> hash(0) == hash(False)
True
>>> 1 == True
>>> True
>>> 0 == False
>>> True
... est garanti dans Python 3.x .
Ce qui signifie que vous ne pouvez pas avoir les deux dans un ensemble :
>>> set([True, 1])
{True}
>>> set([False, 0])
{False}
Les hachages étant égaux, c'est tout aussi important que les objets sont égaux, car des objets qui sont "égaux" peuvent produire des hachages différents et vice versa :
class Foo:
def __init__(self, x): self.x = x
def __hash__(self): return 1
def __eq__(self, other): return self.x == other.x
class Bar:
def __init__(self, x): self.x = x
def __hash__(self): return 2
def __eq__(self, other): return self.x == other.x
>>> x = Foo(3)
>>> y = Bar(3)
>>> x == y
True
>>> hash(x) == hash(y)
False
>>> set([x, y])
{<__main__.Bar at 0x56ed278>, <__main__.Foo at 0x5707390>}
Vous pouvez également avoir un set
qui contient des éléments avec les mêmes hachages, si ces éléments ne sont pas égaux :
>>> hash('a')
-904409032991049157
>>> hash(-904409032991049157)
-904409032991049157
>>> hash('a') == hash(-904409032991049157)
True
>>> set(['a', -904409032991049157])
{-904409032991049157, 'a'}
Ce comportement est no garanti dans Python 2.x, pour la simple raison que True
y False
ne sont pas des mots-clés réservés (ce changement a été introduit dans la version 3.x ). Vous pouvez les réaffecter (bien qu'il soit préférable de ne pas le faire), il n'y a donc aucune raison pour que le même comportement s'applique à Python 2.x :
>>> True = 5
>>> hash(True) == hash(1)
False
>>> set([1, True])
set([1, 5])
Mais ne laissez pas le fait que True
a été remplacé par 5
vous décourager ! On peut abuser de la représentation d'une classe pour faire croire que True
est vraiment dans le jeu :
class Foo(object):
def __repr__(self):
return('True')
>>> True = Foo()
>>> set([1, True])
set([1, True])
Il est évident que les deux derniers extraits de code sont de mauvaises pratiques et ne servent qu'à des fins de démonstration. L'essentiel est que des objets égaux ayant le même hash ne peuvent être contenus dans le même fichier set
et dans Python 3.x, 1
y True
y 0
y False
auront toujours le même hash, et seront toujours égaux.
1 votes
Si
true
est égal à 1 etfalse
est 0, true est déjà dans l'ensemble et ne sera donc pas ajouté à nouveau.2 votes
print({0, False})
0 votes
Mon Python 3.5.1 dit
{True, 2, 4, 7}
et le 1 est parti. Python est parfois impythique1 votes
@ThomasWeller Considérant que
__future__
est toujours en pleine croissance, il semble que Python 4 sera ce que Python 3 était à Python 2.0 votes
@wizzwizz4 J'espère sincèrement que Python 4 sera une transition plus douce que la 3, avec beaucoup plus d'attention portée à la compatibilité entre les versions. (Par exemple, avoir un moyen d'utiliser des types intégrés plus récents qui sont modifiés de manière incompatible, à la manière de
str
ydict
dans Python 3).0 votes
@ThomasWeller C'est un ensemble. Il n'y a pas de garantie d'ordre. Si deux objets ont le même hash et se comparent de manière égale, il n'y a aucun moyen de savoir lequel se retrouvera dans l'ensemble, et votre code ne devrait pas dépendre d'un choix particulier.
0 votes
@jpmc26 Le plus grand
__future__
Les changements semblent concerner les annotations et des éléments "triviaux" similaires ; rien d'important commeprint
-n'est plus un mot-clé.0 votes
@jpmc26 Si True == 1, comment Python peut-il même décider d'imprimer True au lieu de 1 ?
0 votes
@ThomasWeller J'ai trouvé jusqu'à présent que ce qui est en premier sera édité. Par exemple, si vous mettez {1,True, 5,6}, vous obtiendrez 1 en premier alors que {True,1,5,6} me donne True.
0 votes
@DJPoland : Exactement le contraire sur ma machine 3.5.1 et 2.7.11 :
{1, 2, 7, True}
donne{True, 2, 7}
. Le dernier gagne2 votes
@ThomasWeller
id(1) == id(True)
donneFalse
. Ce sont des objets différents, bien qu'ils soient égaux et aient le même hachage.True
est une instance debool
y1
est une instance deint
qui est une classe parentale debool
.==
n'est pas une comparaison d'identité. La réponse ici est de ne pas fairebool
yint
dans le même ensemble. Pourquoi les mélanger ?0 votes
Cela me rappelle le classique
{True: 'yes', 1: 'no', 1.0: 'maybe'}
qui est évalué à{True: 'maybe'}
parce quebool
est une sous-classe deint
avec des valeurs0
y1
ce qui signifie queTrue
&False
hachent les mêmes clés de dictionnaire ou d'ensemble et sont donc "identiques" à leurs valeurs entières en termes d'appartenance à un ensemble.0 votes
Ajoutez maintenant
0j
,1j
,decimal.Decimal('0')
,decimal.Decimal('1')
,fractions.Fraction(0, 1)
,fractions.Fraction(1, 1)
,0.0
y1.0
dans le mélange. Le test des jeux utilise le hachage et tests d'égalité pour déterminer si un objet fait partie de l'ensemble.1 == True == 1.0 == 1j == decimal.Decimal('1') == fractions.Fraction(1, 1)
et ils ont tous la même valeur de hachage.