# There's more to error handling than catching
# try / except / else / finally — the full picture

# ─────────────────────────────────────────────
# else — when everything worked
# ─────────────────────────────────────────────

try:
    age = int(input("Enter your age: "))
except ValueError:
    print("Numbers only, please.")
else:
    print(f"Your age is {age}.")    # only runs if no error

# try succeeds — else runs
# try fails    — except runs, else skipped

# ─────────────────────────────────────────────
# finally — always runs
# ─────────────────────────────────────────────

try:
    age = int(input("Enter your age: "))
except ValueError:
    print("Numbers only, please.")
finally:
    print("Thank you for using this program.")

# valid input or not — finally always executes

# ─────────────────────────────────────────────
# All four together
# ─────────────────────────────────────────────

def get_age():
    try:
        age = int(input("Enter your age: "))
    except ValueError:
        print("Numbers only, please.")
        return None
    else:
        print(f"Valid age received: {age}.")
        return age
    finally:
        print("Input attempt complete.")

result = get_age()
print(result)

# Valid input:
# Enter your age: 25
# Valid age received: 25.
# Input attempt complete.
# 25

# Invalid input:
# Enter your age: abc
# Numbers only, please.
# Input attempt complete.
# None

# ─────────────────────────────────────────────
# Quick reference
# ─────────────────────────────────────────────

# try:       — code that might fail
# except:    — runs if try failed
# else:      — runs if try succeeded, skipped if except ran
# finally:   — always runs — success or failure
#
# you don't need all four — use only what you need
# finally runs even if there's a return inside try or except
