Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does assigning to True/False not work as I expect?

As part of answering another question, I wrote the following code whose behaviour seems bizarre at first glance:

print True                    # outputs true True = False;    print True   # outputs false True = True;     print True   # outputs false True = not True; print True   # outputs true 

Can anyone explain this strange behaviour? I think it has something to do with Python's object model but I'm not sure.

It's version 2.5.2 under Cygwin.

like image 813
paxdiablo Avatar asked Jan 13 '10 07:01

paxdiablo


People also ask

What is False Python?

In Boolean logic "False" is a negative truth-value representing nothing. Often represented as zero, several programming languages have a separate keyword and separate type to represent "False". In Python, the type “bool” represents the Boolean values: "True" and "False".

Is True equal to 1 in Python?

Because True is equal to 1 and False is equal to 0 , adding Booleans together is a quick way to count the number of True values.

Does 1 equal True or false?

1 is considered to be true because it is non-zero. The fourth expression assigns a value of 0 to i. 0 is considered to be false.


2 Answers

Python has these two (among others) builtin objects. They are just objects; in the beginning, they don't have any names yet, but to know what we refer to, let's call them 0x600D and 0xBAD.

Before starting to execute a Python (2.x) script, the name True gets bound to the object 0x600D, and the name False gets bound to the object 0xBAD, so when the program refers to True, it looks at 0x600D.

Because 0x600D and 0xBAD know that they are usually used by the names True and False, that's what they output when they get printed, i.e. the __str__ method of 0x600D returns 'True' and so on.

True = False 

now binds the name True to a different object. From now on, both names True and False refer to the same object 0xBAD, which, when printed, outputs False.

True = True 

doesn't really do anything: It takes the object referred to by the name True, and binds the new (and old) name True to this object. Since (because of the previous step) True refers to 0xBAD before this, it still refers to 0xBAD after this. Hence, printing still outputs False.

True = not True 

first takes the object that the name True is bound to, which is 0xBAD. It gives this object to the not operator. not doesn't care (or know) what name is used here to refer to 0xBAD, it just knows that when given 0xBAD it should return 0x600D. This return value is then given to the assignment operator =, binding the name True to this object.

Since the name True now once more refers to the object 0x600D, calling print True outputs True, and the world is good again.

like image 87
balpha Avatar answered Oct 19 '22 09:10

balpha


Imagine this instead:

A = True B = False  print A           # true A = B;  print A   # false A = A;  print A   # false, because A is still false from before A = not A; print A # true, because A was false, so not A is true 

The exact same thing is going on, but in your version it's confusing, because you don't expect that you can redefine True and False.

like image 44
James Avatar answered Oct 19 '22 09:10

James