Skip to content
CogniSkill

LESSON 2 OF 4

Make decisions and work with collections

Practice notesBooks for further learning

Translate the requirement before coding

The report's rule is: a valid percentage strictly below ten requires review. A valid percentage is an integer between zero and one hundred, inclusive. Exactly ten is OK. An invalid value must be reported separately. Write these statements next to your test cases before choosing an operator.

An if statement selects a branch using a condition. elif checks another condition when earlier branches did not match. else handles the remaining path. Indentation identifies which statements belong to a branch. Use consistent spaces and let your editor help; visual alignment that mixes tabs and spaces can be misleading.

free_pct = 10
if not 0 <= free_pct <= 100:
    status = "INVALID"
elif free_pct < 10:
    status = "REVIEW"
else:
    status = "OK"
print(status)

At ten the output is OK. At nine it is REVIEW. At 101 it is INVALID. The invalid check comes first so an impossible value cannot be classified as healthy just because it is greater than ten. A syntax-valid programme can still encode the wrong requirement.

Deliberately replace < 10 with <= 10. Nine and eleven still behave plausibly; ten changes to REVIEW. That demonstrates why a boundary test is more informative than two comfortable normal cases. Restore the correct condition and keep the ten-percent case in your test suite.

Lists hold a sequence; dictionaries name fields

A list stores ordered values. A dictionary associates keys with values. Neither structure automatically validates the business meaning of its contents. For an inventory row, named fields are clearer than unexplained positions.

rows = [
    {"host": "LAB-A", "free_pct": "9"},
    {"host": "LAB-B", "free_pct": "10"},
]
print(rows[0]["host"])
print(len(rows))

The first output is LAB-A and the second is 2. Index zero selects the first list item; the host key selects the named field inside that dictionary. A list index tells you where a record is in this input, not which device it represents. Later, an inventory reconciliation should use a stable identifier rather than matching the first expected row to the first observed row.

Accessing a missing key with square brackets raises KeyError. Using get() can be appropriate when absence is an allowed state, but it can also hide a broken schema if you turn every absent field into a harmless default. Distinguish a required column from an optional column before deciding how to read it.

A loop repeats a defined operation

A for loop processes items from an iterable. In the report you will perform the same validation for each input row. The loop does not decide whether all rows are trustworthy. That responsibility belongs to the validation function.

for row in rows:
    print(row["host"], row["free_pct"])

This prints two lines. The loop variable refers to the current dictionary during each iteration. It is not a special copy of every field. If you mutate row, you can also change the dictionary inside rows. That matters when you need to retain original evidence.

Create a new output dictionary rather than adding a status directly to the original input row. Keeping source and output separate makes it possible to verify that the report did not alter the received measurements. It also makes rejected-row review more useful because the original text is still available.

Build a function with one reviewable purpose

A function accepts inputs and returns a result. The caller decides what to do with that result. A pure classification function should not read files, print a table, reset a device or write to a database. Separating those actions reduces the number of things you must understand when a test fails.

def classify_number(free_pct):
    if isinstance(free_pct, bool) or not isinstance(free_pct, int):
        return "INVALID"
    if not 0 <= free_pct <= 100:
        return "INVALID"
    return "REVIEW" if free_pct < 10 else "OK"

assert classify_number(9) == "REVIEW"
assert classify_number(10) == "OK"
assert classify_number(0) == "REVIEW"
assert classify_number(101) == "INVALID"
assert classify_number(True) == "INVALID"

The Boolean check is intentional: in Python, bool is a subtype of int, but True is not a valid disk measurement under this contract. Code behavior and business meaning are related but not identical. You need a domain rule to distinguish them.

return sends a result back to the caller and exits that function call. print() displays text but does not substitute for returning a reusable result. If a function prints REVIEW and returns nothing, its caller receives None. That can break an aggregation even when the terminal looked correct.

Lab: extend the classification without changing its meaning

Add test cases for -1, 100 and the string "9". Under this function's numeric contract, -1 and "9" are INVALID and 100 is OK. The CSV reader will use a separate conversion step before calling numeric classification. Keeping conversion separate helps you explain whether a failure concerns source text or a valid number outside the permitted range.

Now add a reason to the result. A valid implementation can return {"status": "INVALID", "reason": "not an integer measurement"} for True and a different reason for 101. Do not return a contradictory result such as status OK with reason “out of range.” Test the whole output object when its fields form an acceptance contract.

Evidence laboratory — attempt before reading the solution

Input rows use strings: (A,"100","9"), (B,"200","20"), (C,"0","0"), (D,"100","unknown"). Fields are name,total,free. A valid row requires total>0 and 0<=free<=total. Alert when free/total is strictly below 0.10. Return valid results separately from rejected rows with reasons. Predict outputs, then implement without network access. Do not treat conversion failure as the numeric value zero.

Official reference for further study

YOUR NEXT STEP

Keep building your skills

No directly related CogniSkill book is mapped to this course yet. Continue with the free learning, or compare the publishing catalogue by your next goal.

Explore books by topic and goal →

Sign in to save lesson completion. Reading position is separate from completion.

Practice notes — your working space

Save predictions, outputs and explanations as you work. Notes stay on this browser, not your account; people sharing this browser can access them. Avoid passwords and sensitive data. Export to keep a portable copy, or clear your notes before leaving a shared device.

How was this lesson?

Help us improve this lesson.