George
George

Reputation: 51

Python - 'if not'

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.

Upvotes: 1

Views: 1054

Answers (6)

Jean-François Fabre
Jean-François Fabre

Reputation: 140188

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))

Upvotes: 2

Szabolcs
Szabolcs

Reputation: 4086

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

Upvotes: 1

gen_Eric
gen_Eric

Reputation: 227240

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))

Upvotes: 12

HP Williams
HP Williams

Reputation: 159

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.

Upvotes: 1

spco
spco

Reputation: 63

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.

Upvotes: 1

rresol
rresol

Reputation: 353

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.

Upvotes: 0

Related Questions