To add a bit more to your own answer (should be a comment, but, long and needs formatting):
python2.7
...
>>> import __builtin__
>>> id(True)
7744528
>>> id(__builtin__.True)
7744528
>>> True = 'abc'
>>> id(True)
34386540544
The value from id is (essentially) the internal identity, or "true name" if you like, of an object in Python. (It's literally a C pointer turned into an integer.) The is test compares object-identity.
>>> 1==1
True
>>> id(1==1)
7744528
This shows that the boolean-result of a comparison is the "old" True, the one still available as __builtin__.True.
You re-bound the name __main__.True (your current module at the interpreter >>> prompt is __main__):
>>> True
'abc'
>>> __builtin__.True
True
and:
>>> import __main__
>>> id(__main__.True)
34386540544
>>> __main__.True
'abc'
>>>
This same thing happens quite often in beginners' Python programs when they write functions like:
def foo(list):
...
list is a built-in function, but inside function foo, the name has been re-bound to the argument. Then somewhere in the ... part they get a surprise:
x = list(y)
They expect this to invoke __builtin__.list, but it tries to call their local variable as a function instead.
(It's possible, but not generally good style, to import __builtin__ and call things through those names instead. It's also possible to re-bind the __builtin__ names, but that's an even worse idea. :-) )
Trueisn't a reserved keyword (or whatever Python has).Truehas become a keyword in Python 3, and the assignment would have raisedSyntaxError: assignment to keyword.idis a built in function, yet it's very often reassigned as object property (eg. in Django ORM). I'm not sure if it's "unwary", given thatid()builtin isn't much useful for anything other than debugging.self.idorobject.id(in a namespace). though I have seen (and even written) code likefor id in list_of_uids:etc., so it's a very good point that it's easy to do.