and — both must be true

age = 25
has_license = True

if age >= 18 and has_license:
    print("Can drive")  # Both conditions true

# Returns first False value, or last if all True:
result = 0 and 5  # 0 (first False)
result = 1 and 2 and 3  # 3 (all True, returns last)

or — at least one must be true

age = 16
has_parent = True

if age >= 18 or has_parent:
    print("Can proceed")  # At least one true

# Returns first True value, or last if all False:
result = 0 or 5  # 5 (first True)
result = 0 or "" or None  # None (all False, returns last)

not — negate condition

is_raining = False

if not is_raining:
    print("Go outside")  # True because not False

# Common pattern:
if not user_logged_in:
    print("Please log in")

Combining operators

age = 25
has_license = True
has_car = False

if age >= 18 and has_license and not has_car:
    print("Can rent a car")

# Use parentheses for clarity:
if (age >= 18 or has_parent) and has_license:
    print("Can drive")

Short-circuit evaluation

Python stops evaluating as soon as result is known:

# If first is False, 'and' doesn't check second:
if False and expensive_function():
    pass  # expensive_function() never called

# If first is True, 'or' doesn't check second:
if True or expensive_function():
    pass  # expensive_function() never called

Truthy and falsy

Non-boolean values are evaluated as True or False:

# Falsy: False, 0, "", [], None
# Truthy: everything else

if []:  # False (empty list is falsy)
    print("This won't print")

if [1, 2]:  # True (non-empty list is truthy)
    print("This will print")