How to correctly use `NOT`

Hello ! Could you tell me please why do I get an error when using not without and before it in this case ? Maybe I missed something in the previous lesson:

def applicant_selector(gpa,ps_score,ec_count):
  if gpa>=3.0 and ps_score>=90 and ec_count>=3:
    return "This applicant should be accepted."
  if gpa>=3.0 and ps_score>=90 not ec_count<3:
    return "This applicant should be given an in-person interview."
  else:
    return "This applicant should be rejected."

If I write and ec_count>=3 instead of not ec_count<3 it is ok. If I write “and not” it’s also ok.

1 Like

not is a unary operator, meaning it has one operand, the expression on its right, as in not x.

Also, not takes precedence over and and or

So, let us assume that conditions 1, 2 and 3 are all True in the following:
if condition_1 and condition_2 not condition_3:

So, if the parser did not catch it first, the logic would go:

  1. not condition_3 is evaluated, returning False
  2. condition_1 and condition_2 is evaluated, returning True

This leaves True False, which is not a valid Python statement, and which will raise a SyntaxError

6 Likes

Generally we would expect to see a logical AND or OR preceding NOT in the above expression.

Eg.

if A and B and not C:

or,

if A and B or not C:
>>> A = 1
>>> B = 2
>>> C = 0
>>> print (A and B and not C)
True
>>> print (A and B or not C)
2
>>> print (A and B not C)

  File "main.py", line 9
    print (A and B not C)
                       ^
SyntaxError: invalid syntax
4 Likes

… was exactly the point I was trying to make.

1 Like

Sheesh! Must have glossed right over that, focused on the little green man and missed the elephant in the room. My bad.

2 Likes

This is my solution, i hope it helps you guys.

def applicant_selector(gpa,ps_score,ec_count):
if gpa >= 3.0 and ps_score >= 90 and ec_count >= 3:
return “This applicant should be accepted.”
elif gpa >= 3.0 and ps_score >= 90 and ec_count <= 3:
return “This applicant should be given an in-person interview.”
else:
return “This applicant should be rejected.”

print(applicant_selector(3.0,91,1))

Since there are two conditions that must be met in the approval process, we can test for them first, and eliminate anyone who should not be considered.

>>> def applicant_selector(gpa,ps_score,ec_count):
        consider = gpa >= 3 and ps_score >= 90
        if not consider: 
            return "This applicant should be rejected."
        return "This applicant should be accepted." \
        if ec_count >= 3 \
        else "This applicant should be given an in-person interview."


>>> print(applicant_selector(3.0,91,1))
This applicant should be given an in-person interview.
2 Likes

Hi, when do I use the parentheses? In this case, they didn’t needed the parentheses between gpa>=3.0, ps_score>=90 and ec_count>=3. But they used the parentheses in the exercises before.

def applicant_selector(gpa, ps_score, ec_count):
if gpa >= 3.0 and ps_score >= 90 and ec_count >= 3:
return “This applicant should be accepted.”
elif gpa >= 3.0 and ps_score >= 90 and ec_count < 3:
return “This applicant should be given an in-person interview.”
else:
return “This applicant should be rejected.”

Parens, as they are commonly known, are seldom required in an expression unless we wish to re-order the precedence by grouping operations into what will become a single operand in the overall expression.

Eg.

>>> A = 1
>>> B = 1
>>> C = 0
>>> A and B and C
0
>>> A and not B and C
False
>>> A and not (B and C)
True
>>> 

This is a poor example, but it opens the door for lots of experimentation in multi operand expressions. Start with a simple example, work it about in myriad ways and make note of the outcome. Be sure to have a clear idea of, why that outcome?

Below I’ll use square brackets to denote the operands…

[A] and [not B] and [C]

then,

[A] and not [([[B]] and [[C]])]

We’ve re-ordered the operations from the earlier example. Now the [[ ]] operation is carried out before the [ ] operation. If A is truthy, then it (the nested operation) is carried out before NOT is applied to the outcome of that operation.

1 Like

try

and not ec_count<3

Can you please help me understand the logic for :
print (A and B and not C) is True
print (A and B or not C) is 2

I haven’t seen logical operators inside print() functions.
Thanks!

The expression is evaluated, the result is given to print. This has no effect on how the expression is evaluated.

print(1 + 2)

Same as with math from third grade, you’ve got a bunch of operators, pick the operator with the highest precedence, evaluate it, replace the inputs and the operator with the result, and then pick the operator that comes next. Continue until you only have a single value. A function call is just another operator, and everything inside the parentheses has to be evaluated before evaluating the function call.

1 Like

Makes more sense now. Thank you.

I think part of the problem with the “not” syntax is that the true is the statement above. Should be … not ec_count>=3. Additionally, I’ve found that enclosing your conditions in () helps.

Did you try…

if (gpa>=3.0) and (ps_score>=90) and (not ec_count >=3):

I’m a “newbie” too, so it’s possible that I’m off base on some of my thoughts too.

In what way it helps will be for the user to determine. I only use grouping when it is necessary for precedence. Python does a pretty good job, otherwise.

>=

has precedence over,

and, or, not

so will be evaluated before the logical evaluation, which follows its own precedence rules,

not, then and, then or
if gpa>=3.0 and ps_score>=90 and not ec_count >=3:

still evaluates correctly with no brackets.


       1                   2                      3
if gpa >= 3.0 and ps_score >= 90 and not ec_count >= 3:
               5                  6   4

The numbers indicate order of operations.