A few examples will make it more obvious:
In [7]: foo = 1000
In [8]: bar = 1000
In [9]: foo is bar # same value but different objects so identity test is False
Out[9]: False
In [10]: foo == bar # equality test is True
Out[10]: True
In [11]: id(foo) # both have different id's
Out[11]: 41007616
In [12]: id(bar)
Out[12]: 40841432
In [13]: foo = bar # now make foo point to the object bar
In [14]: foo is bar # now foo is bar so identity check is True
Out[14]: True
In [15]: id(bar) # matching id's
Out[15]: 40841432
In [16]: id(foo)
Out[16]: 40841432
To compare values use == to check identity use is
Something to be aware of is e small integers -5 to  256 and strings are cached and reused in python so  if you assign a = 10 and b = 10,they actually both point to the same object so a is b . 
In [20]: a = 256    
In [21]: b = 256
In [22]: a is b
Out[22]: True
In [23]: a = 257
In [24]: b = 257    
In [25]: a is b
Out[25]: False
In [26]: foo = "foo"
In [27]: bar = "foo"   
In [28]: foo is bar
Out[28]: True
In [29]: foo = "$bar"
In [30]: bar = "$bar"
In [31]: foo is bar # now False because it does not start with an _ or a letter
Out[31]: False
strings are only cached if they start with an underscore or a letter and contain only letters, numbers or underscores:
A final example of why is __main__ fails:
# first  __main__  object inside locals dict, second is just a string __main__
print id(locals()['__name__']),id("__main__")  
print (locals()['__name__']) is "__main__" # so not the same object 
print (locals()['__name__'])  == "__main__" # but == strings
if __name__ == "__main__":
    print id(locals()['__name__']), id(__name__ ) # same id's 
    print (locals()['__name__']) is __name__ ) # same object stored in locals
140168071262544 140168071262592
False
True
140168071262544 140168071262544
True