Why does Python only install False and Zero?

when creating a set:

>>> falsey_set = {0, '', False, None} # set([False, '', None]) >>> falsey_set = {False, '', 0, None} # set([0,'', None]) >>> # adding an item to the set doesn't change anything either >>> falsey_set.add(False) # set([0,'',None]) 

or a dictionary that mimics behavior somewhat:

 >>> falsey_dict = {0:"zero", False:"false"} # {0:'false'} # that not a typo >>> falsey_dict = {False:'false', 0:'zero'} # {False: 'zero'} # again, not a typo >>> falsey_set.add(()) # set([0,'', None, ()]) >>> falsey_set.add({}) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'dict' >>> falsey_dict[()] = 'list' # {False:'zero', ():'list'} >>> falsey_dict({}) = 'dict' Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'dict' 

0 and False always remove each other from the set. In the dictionaries, they are completely incorrect. Is there a reason for this ? Although I understand that Booleans are made from integers in Python. What is Pythonic reasoning in order to act this way in the context of sets (I don't care too much about dictionaries)? Since it is useful when comparing rights, for example:

 >>> False == 0 # True 

In differentiation, the obvious meaning:

 >>> False is 0 # False 

I was looking through the documentation and cannot find a link to the behavior

Update

@delnan I think you hit a nail on the head with the hash determinism that you mentioned in the comments. Since @mgilson notes that both False and 0 use the same hash function, however, object and many of its subclasses (i.e. super ) that have the same hash . It seems that the key is in the phrase Hashable objects which compare equal must have the same hash value from the documentation . Since False == 0 and both are hashed, their outputs must be determined using the Python definition. Finally, the hashable definition indicates how sets use hashability in a membership set with the following: Hashability makes an object usable as a dictionary key and a set member, because these data structures use the hash value internally. So far, I still do not understand why they both use the same hash function - I can agree with this indentation.

If we all agree, then someone will offer a polished answer, and I will accept it. If there can be any improvement, or if I'm not in the database, please let him know below.

+8
python set
source share
2 answers

This is because the hash of False and 0 with the same value and are equal.

The reason that they hashes with the same value is because bool is a subclass of int , so bool.__hash__ just calls the same basic mechanics that int.__hash__ calls ...

 >>> bool.__hash__ is int.__hash__ True 
+3
source share

First, try to explain what happens at the beginning, with your falsey_set and falsey_dict , so you see that this is not "wrong", but actually only a possible consistent solution. To do this, we will temporarily remove the bool from the image and use something that more people intuitively understand: decimal numbers.

 >>> numset = {3, 5, 3.0, 4} # {3.0, 4, 5} >>> numset.add(3) # no change 

I hope you agree that this is how set should work. If you do not, then it seems that either you think that 3 and 3.0 are actually not equal, or you think that for a dial-up it should be allowed to have equal elements. Neither of these are truly productive IMO beliefs.

(Of course, one of 3 and 3.0 ends in the set, it is a matter of handling the displays, and the set is a bit strange, because it is an atrophied dict where the key and value are the same. But it is consistent and specified in Pythton. At the moment, of course, they cannot both be in the set.)

Another point: as you can see, a thing that I can add to my set (for example, 4 and 5 ) can add many more things to my set). The same thing, the fact that you can add many other false things to your set (for example, '' and None ) does not matter at all. Truth is a red herring. A set may have true elements and false elements. That which cannot be is equal to equal elements.

 >>> numdict = {3:"a", 3.0:"b"} # {3:"b"} 

It looks strange at first sight, but it’s actually much clearer what happens, since the keys and values ​​are separate. Python rules are accurate: read the dict display from left to right, take each pair a: b, then if key a is already in dict, update its value to b, otherwise insert key a in dict with value b.

Using this algorithm, I assume that it is obvious how the last ending ends like that, and all the other actions that you noticed. The important thing is that, as in the set, what you really need in the dict should have only one value for any given key. The presence of two equal keys in the same dictation will be an invitation to disaster, because then you can assign them different values.

So, in a nutshell: I think you dug yourself too deep with hash functions and other implementations. This is a good way to see how Python does X as soon as you realize that X is the right thing. But first you should see that X is the right thing. And I hope I showed you this now. A set cannot have the same elements. He will defeat the widely used set target by removing duplicates. Both 3 and 3.0 are really equal. This has nothing to do with types, some investments are so natural that we erased them at the mathematical level.

Of course, this leaves the question "why are 0 and False really equal"? In fact, the answer is not entirely different: just another mathematically erasable attachment that is so incredibly useful, we will have to jump over many funny hoops without it. Read more about this on the Iverson bracket. ;-) But in any case, it seems you know about this part. Above was what was problematic, I think.

0
source share

All Articles