Subtract boolean from float in python [duplicate] - python

This question already has answers here:
Is False == 0 and True == 1 an implementation detail or is it guaranteed by the language?
(3 answers)
Closed 9 years ago.
Anyways when debuging my code I found statement that basically subtracted boolean from float.
Then I tried following in python console:
>>> 15.0 - True
14.0
>>> 15.0 - False
15.0
Can anyone explain to me:
Why subtracting booleans from numeric types is legal (the docs only state that you can do and, not and or on boolean values: http://docs.python.org/3/library/stdtypes.html#boolean-operations-and-or-not)
Has this any practical use?

It is legal, because bool is a subclass of int:
>>> bool.__bases__
(<type 'int'>,)
>>> True == 1
True
>>> False == 0
True
Yes, it has some practical application. For example it was possible to do something like that before ternary statement was introduced:
result = [value_if_false, value_if_true][condition]
Which basically does what would be done in this code:
if condition:
result = value_if_false
else:
result = value_if_true
Other practical usages are:
you can sum several checks / booleans to receive number of results equaling True,
you can multiply by the result of the check:
result = can_count_a * a + can_count_b * b

http://docs.python.org/3/library/stdtypes.html#boolean-values
Boolean values are the two constant objects False and True. They are used to represent truth values (although other values can also be considered false or true).
In numeric contexts (for example when used as the argument to an arithmetic operator), they behave like the integers 0 and 1, respectively.
not really nowadays, but you can write
result = numeric_value * a_bool (this one is used a lot, for example, in shader languages)
instead of
result = numeric_value if a_bool else 0
or
result = (value_if_false, value_if_true)[a_bool]
Don't do any of that though.
It's mostly what people with experience in lower-level languages expect, why take that away from them? In C, true and false are still macros for 1 and 0.
Before 2.3, there was no bool type in Python as well, so when it was introduced making it a subclass of int made sure no code was broken.

True evaluates to 1 and False evaluates to 0.
>>> True is 1
False
>>> True == 1
True
>>>
Bool is a subclass of int. As stated in PEP-285:
6) Should bool inherit from int?
=> Yes.
In an ideal world, bool might be better implemented as a separate
integer type that knows how to perform mixed-mode arithmetic.
However, inheriting bool from int eases the implementation enormously
(in part since all C code that calls PyInt_Check() will continue to
work -- this returns true for subclasses of int). Also, I believe
this is right in terms of substitutability: code that requires an int
can be fed a bool and it will behave the same as 0 or 1. Code that
requires a bool may not work when it is given an int; for example, 3 &
4 is 0, but both 3 and 4 are true when considered as truth values.
This isn't of any much practical use and there are other answers with sudo examples of using bools. I thought it would be good to have some real examples:
f,b="Fizz","Buzz"
print "\n".join([["",f,b,f+b][(x%3==0) + 2*(x%5==0)] or str(x) for x in range(1,101)])
The section in question:
["",f,b,f+b][(x%3==0) + 2*(x%5==0)]
The selection of the return each line is based on two boolean expressions, if both are true we get (True) + 2*(True) which evaluates to 4 which is a fizzbuzz. Not too hard to understand once you get used to the idea that True == 1 and False == 0
Further more keeping with the theme:
print '\n'.join(['Fizz'*(not i%3) + 'Buzz'*(not i%5) or str(i) for i in range(1, 101)])
This example relies on what happens when you multiply strings in python:
>>> "Noelkd" * False
''
And that not True evaluates to 0:
>>> not True == 0
True
Uses for this fall into two categories:
Making harder to read code.
Competing in code golf competitions.

Related

Python Exponentiating Operator

Could someone help me to understand the following statement?
Why this is True:
3.0 == 3
but this one not?
4 ** 0.5 != 2
(4**0.5 = 2.0, and according to above statement 2.0 is equal to 2), but I get False. WHy?
The != operator does the opposite of ==.
(In your first example, you wrote = but I think you mean ==.)
With !=, it evaluates True if the two numbers are not equal to each other, otherwise it is False. (Here, "equal" can include an integer and a floating point number having the same numerical value.)
So here:
>>> 4 ** 0.5 != 2
False
>>> 4 ** 0.5 == 2
True
Unlike some languages, Python does not care about floats and ints when it comes to comparing. It will treat 4 and 4.0 as the exact same when comparing them to other numbers. You can debate the reliability of this feature of Python, but for the purposes of answering this question this is relevant.
Now we know this, we can see that 4 * .5 is the same is 2.0 which is the same as 2. The actual reason the second argument is false has nothing to do with the number being a float or not, but actually to do with the operator you are using.
== will return true if both sides of the equation ARE equal, whereas != will return true if both sides of the equation ARE NOT equal.
The second statement is using the != operator and so is returning false because both sides are equal. If both sides where not equal, it would return false.
Hope this cleared things up!

False matching with 0 in a list python [duplicate]

This question already has answers here:
Differentiate False and 0
(3 answers)
Closed 5 years ago.
this line evaluates to True in python
False in [0,1,2]
because False and 0 are equal after typecasting.
Is there any way to avoid this typecasting?
Something like === operator for list?
(I know that I can handle this case with a loop by explicitly checking for value types, but I am curious if there is some short and sweet trick to do this without a loop).
First of all, there is no typecasting in Python. False == 0 is true because bool is a subclass of int, and the two objects really are equal.
And no, there is no === operator, you need to explicitly test for types if you don't want this to happen:
lst = [....]
testvalue = False
if any(testvalue == elem and type(testvalue) is type(elem) for elem in lst):
# lst contains testvalue and it is the same type
This explicitly asserts that the two objects are the exact same type, disallowing for subclasses.
Yes, this is a loop. But in for a list also uses a loop, only internally, and both the in containment check and any() short circuit, they return True as soon as the first match is found.
Note that this would disallow float equality too. 0.0 == 0 is true too, but by testing for exact types you disallow that as well. The same goes for complex numbers, and Decimal():
>>> 0j == 0 == 0.0 == Decimal('0')
True
bool is just another numeric type here, albeit one limited to the numeric values 0 and 1.
The better approach, going forward, is to use type hinting in your code; the type hints checker would catch issues like you using booleans where integers or numbers are expected.
If you really feel the need to do the same you can as follows.
False in filter(lambda x: isinstance(x, bool), [0, 1, 2])
Or as #JonClements suggested
any(x is False for x in [0, 1, 3]) # Since immutable values (including
# boolean) are instantiated only once.
However, such use case seldom arises where you need to differentiate between 0 and False as both are falsy as far as Python is concerned. Perhaps, you need to re-think your use-case.
You can use "is" keyword for this.
>>> False == 0
True
>>> False is 0
False

Boolean logic in Python [duplicate]

This question already has answers here:
Is False == 0 and True == 1 an implementation detail or is it guaranteed by the language?
(3 answers)
Closed 8 years ago.
Can someone help to explain the following:
1 and 5
5 and 1
The above gives 5 and 1 respectively. Q1: Why is the and operator not commutative?
Next:
1==True # gives True
However:
5==True
5==False
both give False. Q2: Why?
https://docs.python.org/2/library/stdtypes.html section 5.1 says "... All other values are considered True", so 5 should be True.
From the documentation:
The expression x and y first evaluates x; if x is false, its value is returned; otherwise, y is evaluated and the resulting value is returned.
The expression x or y first evaluates x; if x is true, its value is returned; otherwise, y is evaluated and the resulting value is returned.
Note that here, if x is false means if bool(x) == False.
The answer to your first question about and is that the result of the and is the value of the first expression if it is False-like (0, False, None, etc.), otherwise it is the value of the second expression. A bunch of programming languages share this sort of construct; in some languages like Bash and Perl it's idiomatic to rely on it extensively. In Python we mostly use and for regular boolean logic and rely on it less often for short-circuiting.
As for 1==True being true but 5==True being false, well, frankly I wish 1==True also returned false but obviously it's too late to change it now. :)
In answer to your second part:
It's true that all non-zero integers are "Truthy" but this does not mean that 5 == True will return True. The == operator is comparing value and, when comparing values, 5 is not equal to True. If you compare bool(5) == True then that will return True. When you do if 5: what you actually are doing is if bool(5):.
The reason that 1 == True returns True is that in Python the boolean class is a subclass of int, with True being represented by 1 and False being represented by 0. So 1 == True returns True because they are equal.
Note that, as discussed in this question, this is NOT GUARANTEED in Python 2.x as True and False can be re-defined. In Python 3.x they are keywords which will always be equal to 1 and 0, respectively.

"A is not B" vs "A is (not B)"

I'm a little bit scared about the "is not" operator and the possibility that "is not X" is interpreted when "is (not X)" was intended. Do exist some expressions A and B such that:
A is not B
is different from
A is (not B)
?
addendum.
Is it considered good practice to use this operator? Should't not (A is B) be preferred?
They're definitely different. The latter case evaluates not X in a boolean context first and then checks to see if the two objects are the same object (either True or False).
Consider:
False is not []
This expression is trivially True since False and [] are quite clearly different objects. 1
vs.
False is (not [])
This expression is False since not [] evalutes to True and False and True are different objects.
Of course, this is just one example. It gets even easier to find examples if you don't use False and True explicitly as the second expression will always be False and the first expression will (almost) always be True...
3 is not 0 # True
3 is (not 0) # False
1Note that is not is a single operator in the same vein as not in.
Yes:
A = 0
B = 1
Try it and you'll be really scared:
>>> A = 0
>>> B = 1
>>> A is not B
True
>>> A is (not B)
False

Is False == 0 and True == 1 an implementation detail or is it guaranteed by the language?

Is it guaranteed that False == 0 and True == 1, in Python (assuming that they are not reassigned by the user)? For instance, is it in any way guaranteed that the following code will always produce the same results, whatever the version of Python (both existing and, likely, future ones)?
0 == False # True
1 == True # True
['zero', 'one'][False] # is 'zero'
Any reference to the official documentation would be much appreciated!
Edit: As noted in many answers, bool inherits from int. The question can therefore be recast as: "Does the documentation officially say that programmers can rely on booleans inheriting from integers, with the values 0 and 1?". This question is relevant for writing robust code that won't fail because of implementation details!
In Python 2.x this is not guaranteed as it is possible for True and False to be reassigned. However, even if this happens, boolean True and boolean False are still properly returned for comparisons.
In Python 3.x True and False are keywords and will always be equal to 1 and 0.
Under normal circumstances in Python 2, and always in Python 3:
False object is of type bool which is a subclass of int:
object
|
int
|
bool
It is the only reason why in your example, ['zero', 'one'][False] does work. It would not work with an object which is not a subclass of integer, because list indexing only works with integers, or objects that define a __index__ method (thanks mark-dickinson).
Edit:
It is true of the current python version, and of that of Python 3. The docs for python 2 and the docs for Python 3 both say:
There are two types of integers: [...] Integers (int) [...] Booleans (bool)
and in the boolean subsection:
Booleans: These represent the truth values False and True [...] Boolean values behave like the values 0 and 1, respectively, in almost all contexts, the exception being that when converted to a string, the strings "False" or "True" are returned, respectively.
There is also, for Python 2:
In numeric contexts (for example when used as the argument to an arithmetic operator), they [False and True] behave like the integers 0 and 1, respectively.
So booleans are explicitly considered as integers in Python 2 and 3.
So you're safe until Python 4 comes along. ;-)
Here's the PEP discussing the new bool type in Python 2.3: http://www.python.org/dev/peps/pep-0285/.
When converting a bool to an int, the integer value is always 0 or 1, but when converting an int to a bool, the boolean value is True for all integers except 0.
>>> int(False)
0
>>> int(True)
1
>>> bool(5)
True
>>> bool(-5)
True
>>> bool(0)
False
In Python 2.x, it is not guaranteed at all:
>>> False = 5
>>> 0 == False
False
So it could change. In Python 3.x, True, False, and None are reserved words, so the above code would not work.
In general, with booleans you should assume that while False will always have an integer value of 0 (so long as you don't change it, as above), True could have any other value. I wouldn't necessarily rely on any guarantee that True==1, but on Python 3.x, this will always be the case, no matter what.

Categories

Resources