Does the position of 'not' matter when negating statements (see examples below)?

Often in programming, we use ‘not’ BEFORE the condition we’d like to negate. For example:

if not 5 in range(x, y):
  return True
else:
  return False

would return True if x = 6 and y = 10 for instance.
Or, if we had x = 0 and y = 6 then it would return False. This is as we’d expect.

However, the code:

if 5 not in range(x, y):
  return True
else:
  return False

would also return the same values and this second articulation of the code seems much more readable.

So, does the position of the ‘not’ matter in cases like this? Are there any cases where it would? And if so, please give examples, because I’m not sure why conventional coding practises dictate that we should use the first articulation.

If it’s relevant, I am learning Python 3 and I’m still a beginner.

Yes, in Python 3, the logical switch must be placed between the two logical statements.

if (statement 1) (logical switch) (statement 2)

Where the logical switch can be a comparison, or an operator like and or not.

The reason ‘traditional coding practises’ dictate the former method is because many other languages like C++ and Java require that format. Python takes a different approach to formatting statements where it aims to be more human readable and easier to comprehend than its predecessors.

Oh, also, another thing: the full logical operator is not in. A not equal operator is actually !=, they are two different logical functions. One is used to check whether the two statements are equal (!=) while the other one is used to determine whether the first statement is not present within the second statement (ie, finding a letter in a string)

The result of this is False.

not operates on whatever is to the immediate right. Above we are not interested in 5 but rather its membership in the given range.

not (5 in range(x, y))

Now we evaluate not against the entire expression.

 5 not in ...

Again, we are evaluating the entire expression because of the placement of not. In this case we cannot successfully evaluate the not in range(x, y) without the 5 since the in operator needs an operand on both sides and not is not an operand.

We don’t even need an if…else.

return 5 not in range(x, y)

The return will be a boolean.

Keep in mind that booleans are also integers. 0 is False and vice-versa, and 1 is True, and vice versa. So if there is a 0 in the range, the complete expression would be True.

not 5 in range(0, y) => False in range(0, y) => True

since not 5 is evaluated first.

I can’t ever look smart when you’re around :stuck_out_tongue: Always on my tail, explaining things better than me.

2 Likes

Not better, only supplemental. It’s adding to your excellent explanation.

3 Likes

You say the position matters but as I say I changed the position of not in my example code and they both seem to function exactly the same way, and I’ve used it simlarly in many other instances.

Are you telling me Java and C++ would write: if (logical switch) (statement 1) (statement 2)? Because I don’t see how that would make sense when using ‘and’ or ‘or’.

I’m not sure what you’re saying ‘not equal’ does? If we wanted to check whether a letter was in a string we would just use ‘letter in string’ no?

"

I’m not sure you’ve answered my question. As I say, in my example, the postion of not seems to matter not (pun intended).

We learn something new every day.

>>> a = range(10)
>>> not 5 in a
False
>>> a = range(1, 10)
>>> not 5 in a
False
>>> a = range(6, 10)
>>> not 5 in a
True
>>> 

5 in a is an expression, so that would mean the whole thing is the operand.

So what are you saying? After reading on stack exchange it would seem the two statements are equivalent in my example. I’m not sure the point you’re making here.

No point. Just that I’m now aware that not (when it precedes) is not applied only to the 5 but to the expression, 5 in range(x, y).