← Home

024. Logical Operators

Compose boolean conditions with and/or/not

024. Logical Operators

RAM Manager — Kill Decision Logic

Aryan’s RAM manager has a should_kill(process) function that decides whether to terminate a process. The rules are:

  1. Auto-kill: RSS memory > 500 MB AND the process is marked as killable
  2. Safe to skip: The process name is "system" OR it has pid == 1

He writes both functions, but swaps and for or in the auto-kill check. Now a process with 600 MB RSS is killed even if it is not marked killable (because or only needs one condition to be true). Critical system processes get killed.

The lesson: and requires both conditions; or requires at least one. In security and resource management, using or instead of and almost always means you are too permissive — and the consequences can be severe.


💡 Fun fact: Python uses and, or, not as keywords rather than C’s &&, ||, !. Guido van Rossum chose English words to make code read like prose. Additionally, Python’s logical operators use short-circuit evaluationFalse and expensive_call() never evaluates expensive_call(), which can be used deliberately to avoid unnecessary computation.

⚠️ Watch out: Replacing and with or in a multi-condition check is the classic security mistake — it makes your gate too permissive. A password validator that uses or instead of and will accept any string that has at least one good property, not all of them.

🤔 Think about it: not has higher precedence than and, which has higher precedence than or. So not a or b and c parses as (not a) or (b and c). How would you rewrite this expression with explicit parentheses to make the intended meaning unambiguous?

Learning objectives

  • Use and for “all conditions must be true”
  • Use or for “at least one condition must be true”
  • Use not to invert a boolean

Key concepts

  • logical operators
  • and
  • or
  • not

Try it

Concept detail

Logical operators: and (all True), or (at least one True), not (invert). Short-circuit evaluation: ‘False and anything’ → False (skips right side). ‘True or anything’ → True (skips right side). Truth table: and needs both True; or needs at least one True. not True == False, not False == True, not 0 == True, not “” == True. All non-zero, non-empty objects are truthy in Python.

Solution

def is_valid_password(password):
    has_length = len(password) >= 8
    has_digit = any(c.isdigit() for c in password)
    has_upper = any(c.isupper() for c in password)
    return has_length and has_digit and has_upper

def is_locked_out(attempts, last_attempt_mins_ago):
    return attempts >= 3 and last_attempt_mins_ago <= 30

Tests

def test_valid_password():
    assert is_valid_password("Secure123") == True

def test_too_short():
    assert is_valid_password("Ab1") == False

def test_no_digit():
    assert is_valid_password("SecurePass") == False

def test_no_upper():
    assert is_valid_password("secure123") == False

def test_locked_out():
    assert is_locked_out(3, 10) == True

def test_not_locked_few_attempts():
    assert is_locked_out(2, 5) == False

def test_not_locked_old_attempt():
    assert is_locked_out(5, 60) == False

Resources