为什么我可以在Python的集合中添加布尔值False但不是True?

DJ *_*and 34 python set

我刚开始研究Python中的set数据类型.出于某种原因,每当我将布尔值True添加到集合时,它都不会出现.但是,如果我将False添加到集合中,它将成为集合的元素.当我用谷歌搜索这个问题时,我感到很震惊.

example1 = {1, 2, 7, False}
example2 = {7, 2, 4, 1, True}

print(example1)
print(example2)
Run Code Online (Sandbox Code Playgroud)

输出是:

{False, 1, 2, 7}
{1, 2, 4, 7}
Run Code Online (Sandbox Code Playgroud)

And*_*ely 35

因为在Python 1 == True(和hash(1) == hash(True))中,你的集合中已经有1个.

想象一下这个例子:

example1 = {0, False, None}
example2 = {1, True}

print(example1)
print(example2)
Run Code Online (Sandbox Code Playgroud)

将输出:

{0, None}
{1}
Run Code Online (Sandbox Code Playgroud)

第一组有0,None因为0 == False但是0 != None.使用第二组时1 == True,True不会将其添加到集合中.


use*_*203 15

你失去布尔值的原因set如果它们已经包含0或者1是因为以下行为......

>>> hash(1) == hash(True)
True
>>> hash(0) == hash(False)
True
>>> 1 == True
>>> True
>>> 0 == False
>>> True
Run Code Online (Sandbox Code Playgroud)

... 在Python 3.x中得到保证.

这意味着你不能同时拥有一套:

>>> set([True, 1])
{True}
>>> set([False, 0])
{False}
Run Code Online (Sandbox Code Playgroud)

散列相等的散列与对象相同同样重要,因为"相等"的对象可以产生不同的散列,反之亦然:

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>}
Run Code Online (Sandbox Code Playgroud)

set如果这些项不相等,您还可以包含具有相同哈希值的项目:

>>> hash('a')
-904409032991049157
>>> hash(-904409032991049157)
-904409032991049157
>>> hash('a') == hash(-904409032991049157)
True
>>> set(['a', -904409032991049157])
{-904409032991049157, 'a'}
Run Code Online (Sandbox Code Playgroud)

Python 2.x中无法保证此行为,原因很简单,True并且False不是保留关键字(此更改是在3.x引入的).你可以重新分配它们(虽然最好不要),所以没有理由在Python 2.x中必须保持相同的行为:

>>> True = 5
>>> hash(True) == hash(1)
False
>>> set([1, True])
set([1, 5])
Run Code Online (Sandbox Code Playgroud)

但是不要让True被取代的事实5劝阻你!我们可以滥用类的表示,使其看起来好像True在集合中:

class Foo(object):
    def __repr__(self):
        return('True')

>>> True = Foo()
>>> set([1, True])
set([1, True])
Run Code Online (Sandbox Code Playgroud)

显然,最后几段代码片段是不好的做法,仅用于演示.主要的外卖是相同的哈希相等的对象不能被包含在相同的set,并在Python 3.x中,1True,和0False,将始终具有相同的哈希值,而且将永远是平等的.