Skip to content
← DevOps Foundations

Learning bite

Types, functions, and exceptions

Build a small automation function with explicit inputs and failures.

  • Python
Documentation reviewed2026-10-01 · 3 min read
  1. Why
  2. Predict
  3. Try
  4. Inspect
  5. Explain
  6. Save evidence

Predict before you try

Will one successful input prove that this automation handles missing or invalid input?

Try it: Try changes and explain them →
On this page

Turn a manual decision into a program

Suppose a supplied capacity report says a disk has 20 GiB total and 8 GiB used. A person subtracts, checks that the values make sense, and reports 12 GiB remaining. Python lets us make those steps explicit and repeat them for many reports. These are invented inputs; the program does not inspect your disk.

Work in the capacity-tool directory from the setup lesson with its virtual environment active. In Python, = binds a name to a value; == compares two values. Numbers such as 20 are integers, 0.5 is a float, "20" is a string, and True/False are booleans. None represents an absent value. A string containing digits is still text until you convert it.

Save and run values.py:

python
total = 20
used = 8
remaining = total - used
print(remaining)
print(remaining > 5)
print(int("20") - used)
print("20" + "8")

Expected lines: 12, True, 12, and 208. The last operation joins text. int("twenty") raises ValueError; conversion is a decision about acceptable input, not an automatic repair.

Collections, decisions, and repetition

A list holds ordered items. A dictionary maps keys to values. Access a dictionary value by its key, rather than assuming it has a meaningful position:

python
samples = [{"name": "api", "total": 20, "used": 8},
           {"name": "worker", "total": 10, "used": 9}]
for sample in samples:
    available = sample["total"] - sample["used"]
    if available < 3:
        label = "review"
    else:
        label = "enough for this fixture"
    print(f'{sample["name"]}: {available} GiB, {label}')

Add this below values.py and run it. Expected final lines: api: 12 GiB, enough for this fixture and worker: 1 GiB, review. Indentation groups statements into the loop and branches. for visits each item; if chooses a branch. An f-string inserts expressions into text. This threshold is our exercise rule, not a universal capacity recommendation.

Lists and dictionaries are mutable: their contents can change. Two names can refer to the same collection, so changing it through one name can affect the other. Avoid changing the list you are currently iterating over until you understand those effects.

Extract one responsibility

Save this as capacity.py:

python
def remaining_gib(total: int, used: int) -> int:
    if type(total) is not int or type(used) is not int:
        raise TypeError("capacity values must be integers")
    if total < 0 or used < 0 or used > total:
        raise ValueError("require 0 <= used <= total")
    return total - used

if __name__ == "__main__":
    samples = [{"total": 20, "used": 8}, {"total": 20, "used": 25}]
    for sample in samples:
        try:
            print(remaining_gib(**sample))
        except (TypeError, ValueError) as error:
            print(f"invalid sample: {error}")

def creates a function. Parameters receive the caller's inputs; return gives a result back. Type hints document the intended types but do not enforce them. The explicit checks do. **sample supplies dictionary entries as named arguments, equivalent here to remaining_gib(total=20, used=8).

An exception interrupts normal execution. raise reports the reason; a matching except decides how to handle it. try covers the operation expected to fail. Catching every exception would also hide programming errors you have not accounted for. The exact type check rejects booleans because Python otherwise treats them as integer subclasses.

Run python capacity.py. Expect 12, followed by invalid sample: require 0 <= used <= total. The caller prints; the function only calculates or raises. That separation makes the calculation straightforward to test.

Try changes and explain them

Predict remaining_gib(20, -1), remaining_gib("20", 8), and remaining_gib(0, 0). They produce ValueError, TypeError, and 0, respectively. Zero is a valid result, so treating every false-like value as an error would be a bug.

Add a third valid sample and predict its output before running. Then import remaining_gib from another file: the example loop should stay quiet because of the main guard. Keep capacity.py; the next lesson supplies its inputs from a file.

References: Python introduction↗, control flow and functions↗, data structures↗, and exceptions↗.

Additional primary references: Functions↗.

Prove what you learned

Inspect the result

Record input, returned value/output and expected versus actual failure behaviour.

Explain it in your own words

Explain why your observation supports the stated outcome, and name one thing it does not prove.

Try a small variation

Choose one different valid value and one missing or boundary input; predict both before running.

Your evidence should show

  • Record the context/revision or label the work as a paper or prepared fixture.
  • Compare the prediction with the actual result from “Try changes and explain them”.
  • Record input, returned value/output and expected versus actual failure behaviour.
  • Explain the transfer challenge and retain the same verification question.
Hint

Trace the input, returned value or exception, and observable command result.

Answer guide: compare after predicting

No. Compare a valid input with a defined failing or boundary case and assert the expected result.

Compare this with your actual observation. A paper answer is useful reasoning practice; record execution separately.

Recall shell argument boundaries and exit-status checks. Revisit the previous lesson.

Save the prediction, result and explanation ↓

Your notes and evidence

Record observations, questions, or links to your work. Keep credentials out of your notes.

Loading saved progress…

Back up or restore this path

Progress and notes stay in this browser. A backup contains only this learning path.