Python - 'if not' - python

The following codes
multiples = []
for i in range(1,1000):
if i % 3 == 0 or i % 5 == 0:
multiples.append(i)
addition = sum(multiples)
print addition
and
print(sum([i for i in range(1, 1000) if not (i%3 and i%5)]))
do the same thing.
Now how does the if not part compute in the second code?
What I'm saying is, in the first code the i % 3 == 0 or i % 5 == 0 had to be exclusively stated whereas the same thing is achieved on the second code without the == 0.

Using De Morgan's laws:
i % 3 == 0 or i % 5 == 0
is the same as:
not (i % 3 != 0 and i % 5 != 0)
And in python, when converting a number to a boolean, any non-zero value becomes True.
So instead of doing i % 3 != 0 in the if, you can just use i % 3, because if it's 0 it'll be False and if it's non-zero it'll be True.
Here's python's truth table: https://docs.python.org/3.6/library/stdtypes.html#truth
P.S. sum() can take a generator as an argument, so you can actually just do:
sum(i for i in range(1, 1000) if not (i%3 and i%5))

and and or are boolean operators, not logical & and |. So writing
a == 0 or b == 0
is the same as writing
not a or not b
So they do the same thing
As a conclusion, the best way is to avoid negations in your conditions, don't create extra list comprehension but use generator comprehension instead, and I wouldn't mind testing against zero instead of using not since they're integers after all. I would do this:
print(sum(i for i in range(1, 1000) if i%3==0 or i%5==0))

This is an effect of the way Python converts integers to booleans. The result of i % 3 is 0, 1, or 2, depending on the value of i. In Python 3.x (and by default also in Python 2.x, unless you've reassigned them) all non-zero integers evaluate to False and zero evaluates to True.
Thus if not (i % 3) will evaluate (i % 3) to an integer 0, 1, or 2, and then not will convert these to False, True, True.

In Python 0 is usual interpreted as false. So in the first code block i % 3 == 0 is effectively equivalent to not i % 3. Examples from command line:
>>> 6 % 3 == 0
True
>>> not 6 % 3
True
>>> 7 % 3 == 0
False
>>> not 7 % 3
False
This shortcut of 0 === false appears in many languages and can be a bit confusing if you're not used to it.

In Python every object has a boolean value.
In the case of integers any of them is True except 0.
So in your case when number i can be divided by 3 the expression i % 3 will be 0. But we know that 0 is False. The not operator will negate this expression so not False will become True.
The same holds for not i % 5 as well.
Hope it helps.
Any object can be tested for truth value, for use in an if or while condition or as operand of the Boolean operations below. The following values are considered false:
None
False
zero of any numeric type, for example, 0, 0L, 0.0, 0j.
any empty sequence, for example, '', (), [].
any empty mapping, for example, {}.
instances of user-defined classes, if the class defines a nonzero() or len() method, when that method returns the integer zero or bool value False. [1]
All other values are considered true — so objects of many types are always true.
See also:
https://docs.python.org/2/library/stdtypes.html

see, i % 3 == 0 return true if the condition satisfy. Now, in python suppose:
i = 6
6 % 3 = 0 and 0==0 is true
There fore the result will be true.
In the second case
6 % 3 = 0.
Now, in boolean 0 means false. So by using not it means not false, i.e, true.

Related

Does the 'or' operator or the equality operator have higher precedence in Python? [duplicate]

This question already has answers here:
Why does "a == x or y or z" always evaluate to True? How can I compare "a" to all of those?
(8 answers)
Closed 4 months ago.
Every precedence table I look at for Python states the equality(==) operator is evaluated before the 'or' keyword. Why then is '1' printed for this code? I thought the expression would evaluate as false, and the if block wouldn't run.
number = 1
if number == 0 or 1:
print(number)
How about the following code? Why isn't 'False' printed? Instead, the integer 1 is printed. It confuses me how the variable 'a' gets assigned as 1 instead of as a False boolean value.
number = 1
a = (number == 0 or 1)
print(a)
Well, you are correct. == does evaluate before or. In the case of if number == 1 or 1, what happens is that python evaluates numbers that aren't 0 as True. So the first "argument" (number == 1) will evaluate to False, while 1 will evaluate to True. And False or True will always be True.
The other case (a = (number == 0 or 1)) is a little more tricky. In the case of having an assignment of a variable to multiple expressions chained with or, Python will assign the variable to the first expression that evaluates to True and if it doesn't find any, it will assign to the last expression.
In this case, the first expression (number == 0) is False while 1 on the other hand is True. a therefore gets assigned the value of the second expression, which is 1.
number = 1
if number == 0 or 1:
print(number)
In above if statement, you have two conditions. It always tries to find the boolean expression of the given conditions and block will get executed only when it finds True.
number == 0
First condition evaluates False since the number is 1
boolean(1)
Second condition evaluates True which is why block of code executed and 1 is printed.
Same happened with the other part of your code.
number = 1
a = (number == 0 or 1)
print(a)
Just remember that our code tries to find the True values. Hope, it helps.
See python docs Boolean operations
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.
Going by your example:
number = 1
if number == 0 or 1:
print(number)
# disected
print(number == 0) # prints False
print(False or 1) # prints 1 as it is a truthy value
In your boolean operation the equality operator == is evaluated before the or keyword.
As number == 0 evaluates to False the right side of the or operator gets evaluated. 1 is a true statement so 1 gets returned.
But what if both sides evaluate to False or have a falsy value?
number = 1
if number == 0 or 0:
print(number) # won't print
As number == 0 evaluates to False, 0 is evaluated. That is a falsy value, so the or operation returns False, or in this case the falsy value 0 which evaluates to False in the if statement.

What does the following line accomplish? [duplicate]

This question already has answers here:
How do "and" and "or" act with non-boolean values?
(8 answers)
Closed 2 years ago.
So I was trying to solve an algorithm and while trying to find other solutions to it, I found one which was very short and very fast, just one problem...I can't seem to understand what this line is doing:
Full solution:
def proper_fractions(n):
phi = n > 1 and n
print(phi)
for p in range(2, int(n ** .5) + 1):
if not n % p:
phi -= phi // p
while not n % p:
n //= p
if n > 1: phi -= phi // n
return phi
Line that I don't understand:
phi = n > 1 and n
Please forgive me If it is very easy to understand, I just have never come across something like this, I've only used and in if statements, here is what I changed the line to (I think it works like the other one, but not sure how the other one does exactly what the following line which I changed does):
phi = n if n > 1 else False
Please could someone clear-up how the line that I don't understand works?
As can be seen in the Python docs, Python logical operators are not necessarily "purely Boolean". In particular, and and or are not actually guaranteed to return True or False. Instead, they return one of their operands. Here's how Python defines the value of x and y:
if x is false, then x, else y
"False" in this context does not mean that x has to be the value False. Instead, it just has to be anything with a falsy value, like a zero of any type or an empty sequence or collection.
In this case, when n > 1 evaluates False, the operator short-circuits and returns n > 1, AKA False. But if n > 1 evaluates True, the operator simply returns n without modifying it in any way, as the docs describe.
The truth table for a and b looks like this:
True and True == True
True and False == False
False and True == False
False and False == False
We can observe three things:
When a is True, the result is always the same as b.
When a is False, the result is always False, in other words, it is always the same as a.
When a is False, b is completely irrelevant, so we don't even need to evaluate it.
Note that in Python, True and False are not the only objects that have a boolean value. In fact, every single object in Python has a boolean value. E.g. 0 has a falsey value, "Hello" has a truthy value, and so on.
So, with the optimizations we discovered about the truth table, and the added condition that we need to handle values other than True and False, we can construct the following, revised, truth table:
a and b == a # if `a` is *falsey*
a and b == b # if `a` is *truthy*
This matches up with the documentation of and:
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.
Similar reasoning applies to or:
a or b == b # if `a` is *falsey*
a or b == a # if `a` is *truthy*
So, the result of the line in question:
phi = n > 1 and n
will be that phi is assigned False if n <= 1 and n if n > 1.
The further computation that is performed with phi in turn works because False is equivalent to 0 in a numeric context, i.e.
False + 1 == 1
False - 1 == -1
This makes the rest of the algorithm work, which contains statements like:
phi -= phi // p
Where arithmetic is performed with the value of phi.
See the documentation on the numeric types for details, which contains the following statement [bold emphasis mine]:
There are three distinct numeric types: integers, floating point numbers, and complex numbers. In addition, Booleans are a subtype of integers.
From section 6.11 of 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.
Note that neither and nor or restrict the value and type they return to False and True, but rather return the last evaluated argument. This is sometimes useful, e.g., if s is a string that should be replaced by a default value if it is empty, the expression s or 'foo' yields the desired value. Because not has to create a new value, it returns a boolean value regardless of the type of its argument (for example, not 'foo' produces False rather than ''.)
So it first check if n > 1, if it is true, then it return s n, otherwise it returns False.
First, it's first checking if the first evaluation is True or False (Null value are considered false). Then if it's True, will return the second value. In this case, n.
More details:
> if n = 3
> 1. phi = n > 1 and n
> 2. phi = 3 > 1 and 3
> 3. phi = True and 3
> 4. phi = 3

If shorten, python recursion

i try to write a short golf code without using letters "eiou" and i found that (a,b)[conditions] is equal to if statement, but i have no idea why it doesn't work.
a_factaral=lambda x:(a_factaral(x-1)*x,1)[x==0]
Please for some tips
bool is a subclass of int. False is 0 and True is 1.
>>> True+True
2
Logical predicates like x==0 return a boolean value.
>>> x=0
>>> x==0
True
The logical predicate can act as an index of 0 or 1. If the predicate is False, the index is 0. Otherwise, it's 1.
>>> (1, 2)[x!=0]
1
>>> (1, 2)[x==0]
2
Your function returns a_factaral(x-1)*x if x is anything other than 0, or 1 when x has reached 0 (the stopping point for the recursion).
You could ungolf this as follows:
def a_factaral(num):
if num == 0:
return 1
else:
return a_factaral(num-1) * num
(a_factaral(x-1)*x,1)[x==0] will calculate the first value first, then decide which value to take out depends on the result of x==0.
a_factaral=lambda x:((x!=0 and a_factaral(x-1)*x) or 1) will work for the same function. But in the case you cannot use 'eiou', I have no idea for alternative solution.

Subtract boolean from float 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 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.

Is there a difference between -1 and False in Python?

I have always thought that using -1 in a condition is alway the same as the writing False (boolean value). But from my code, I get different results:
Using True and False:
def count(sub, s):
count = 0
index = 0
while True:
if string.find(s, sub, index) != False:
count += 1
index = string.find(s, sub, index) + 1
else:
return count
print count('nana', 'banana')
Result: Takes to long for interpreter to respond.
Using 1 and -1:
def count(sub, s):
count = 0
index = 0
while 1:
if string.find(s, sub, index) != -1:
count += 1
index = string.find(s, sub, index) + 1
else:
return count
print count('nana', 'banana')
Result: 1
Why does using -1 and 1 give me the correct result whereas using the bool values True and False do not?
string.find doesn't return a boolean so string.find('banana', 'nana', index) will NEVER return 0 (False) regardless of the value of index.
>>> import string
>>> help(string.find)
Help on function find in module string:
find(s, *args)
find(s, sub [, start [, end]]) -> int
Return the lowest index in s where substring sub is found,
such that sub is contained within s[start,end]. Optional
arguments start and end are interpreted as in slice notation.
Return -1 on failure.
>>>
Your example simply repeats:
index = string.find('banana', 'nana', 0) + 1 # index = 3
index = string.find('banana', 'nana', 3) + 1 # index = 0
The -1 version works because it correctly interprets the return value of string.find!
False is of type bool, which is a sub-type of int, and its value is 0.
In Python, False is similar to using 0, not -1
There's a difference between equality and converting to a boolean value for truth testing, for both historical and flexibility reasons:
>>> True == 1
True
>>> True == -1
False
>>> bool(-1)
True
>>> False == 0
True
>>> bool(0)
False
>>> True == 2
False
>>> bool(2)
True
I have always thought that using -1 in a condition is alway the same as the writing False (boolean value).
1) No. It is never the same, and I can't imagine why you would have ever thought this, let alone always thought it. Unless for some reason you had only ever used if with string.find or something.
2) You shouldn't be using the string module in the first place. Quoting directly from the documentation:
DESCRIPTION
Warning: most of the code you see here isn't normally used nowadays.
Beginning with Python 1.6, many of these functions are implemented as
methods on the standard string object. They used to be implemented by
a built-in module called strop, but strop is now obsolete itself.
So instead of string.find('foobar', 'foo'), we use the .find method of the str class itself (the class that 'foobar' and 'foo' belong to); and since we have objects of that class, we can make bound method calls, thus: 'foobar'.find('foo').
3) The .find method of strings returns a number that tells you where the substring was found, if it was found. If the substring wasn't found, it returns -1. It cannot return 0 in this case, because that would mean "was found at the beginning".
4) False will compare equal to 0. It is worth noting that Python actually implements its bool type as a subclass of int.
5) No matter what language you are using, you should not compare to boolean literals. x == False or equivalent is, quite simply, not the right thing to write. It gains you nothing in terms of clarity, and creates opportunities to make mistakes.
You would never, ever say "If it is true that it is raining, I will need an umbrella" in English, even though that is grammatically correct. There is no point; it is not more polite nor more clear than the obvious "If it is raining, I will need an umbrella".
If you want to use a value as a boolean, then use it as a boolean. If you want to use the result of a comparison (i.e. "is the value equal to -1 or not?"), then perform the comparison.

Categories

Resources