Week 1

Stage 1 · Weeks 3–12 · software

Python Programming

Write programs independently

Locked

Scored stage progress

0%

Practice and implementation

0/19

Exercises + milestone requirements owned by this stage

Evidence and gate

0 · 0/18

Artifacts · checked requirements

Why it matters

Purpose of this stage

Write programs independently

Subjects

10 subjects · 45 canonical topics

Each subject states what you should be able to do, an order to work through it in, what to watch for, and the questions a reviewer should be able to ask you at the end. None of it is tracked or scored.

How to work through this subject

An order that works, not a checklist. Nothing here is tracked — the steps sequence this subject’s own topics and add none.

  1. Run `git init` in your learning folder and `git status` immediately, before doing anything else.
  2. Write `.gitignore` first — virtual environment, caches, anything holding a secret — then check `git status` again and watch the noise disappear.
  3. Make one small change, `git add` just that change, `git commit` it with a message you could read back in a month.
  4. Run `git log` and read your own history. If a message tells you nothing, that is feedback about the message.
  5. Add a remote with `git remote`, then `git push`, and confirm in a browser that the code is really there.
  6. Repeat the add/commit/push cycle for every exercise this stage, until it costs you no thought at all.

What to watch for

  • This is deliberately the smallest useful Git. Branching, merging, conflicts and recovery are Stage 2 — reaching for them now buys confusion, not capability.
  • Commit when something works, not at the end of the day. A commit is a checkpoint you can describe in one sentence.
  • The first thing in `.gitignore` should be your virtual environment. The second should be anything holding a secret.
  • `git status` is the Git equivalent of `pwd`: run it when confused, before running anything else.
  • A commit is a decision to keep something. If you cannot say what the commit is for, it is probably two commits.

Curriculum topics

`git init`
Turns a plain folder into a repository, so Git starts tracking what changes inside it.
`git status`
Shows what you have changed, what is staged to be saved, and what Git is ignoring.
`git add`
Chooses which changes go into the next save. Nothing is recorded until you add it.
`git commit`
Records the staged changes permanently, with a message saying what you did and why.
`git log`
Lists the commits you have made, newest first — the history of your work.
`git remote`
Registers the address of a copy of your repository that lives elsewhere, usually on GitHub.
`git push`
Sends your commits to the remote copy, so the work exists somewhere other than your laptop.
`.gitignore` basics
A file listing things Git should never record — virtual environments, caches, secrets, and anything generated.

Resources for this subject

  • REFERENCEgittutorial git-scm.com
    The official introduction to the eight commands Stage 1 actually uses, and nothing beyond them. Pro Git is the Stage 2 resource; this is the smaller reference for saving and publishing work while you are still learning Python.
    Open

A reviewer should be able to answer these

Answer from memory, out loud, before moving on. These are not tracked and do not affect the gate — they tell you whether you actually understand this subject.

  1. What does `git add` do that `git commit` does not?
  2. Why does Git require you to choose what goes into a commit instead of saving everything?
  3. What is the difference between your local repository and the remote one?
  4. What belongs in `.gitignore`, and what goes wrong if a virtual environment is committed?
  5. You wrote a working script but have not run any Git command yet. What is the shortest sequence that gets it onto GitHub?
  6. What does `git log` let you reconstruct that the files on disk alone do not?
  7. What does `git status` tell you, and when in your workflow should you run it?

Exercises

Demonstrated practice · 35% base weight

calculator

warmup ~45 min

A menu-driven calculator supporting the four basic operations, built from functions.

What to implement

  • One function per operation, each returning its result rather than printing.
  • Prompt for two numbers and an operation.
  • Handle division by zero without crashing.
  • Reject non-numeric input and re-prompt.
  • Loop until the user chooses to exit, rather than running once.

Done when

  • Every operation is a function you could import and test.
  • Entering `abc` or dividing by zero produces a message, not a traceback.
  • The program survives ten deliberately hostile inputs in a row.
  • Each operation function can be called from a test with no input prompt involved.

One hint, available after you have made a real attempt.

unit converter

core ~60 min

Convert between units in at least two categories, with conversion logic separated from input handling.

What to implement

  • Support at least two categories, e.g. temperature and length.
  • Each conversion is a pure function taking a value and returning a value.
  • The menu selects a conversion; it does not contain the maths.
  • Round output sensibly and say why you chose that precision.
  • Reject a value that is impossible for its unit, such as a length below zero.

Done when

  • Adding a third category requires no change to the input-handling code.
  • You can convert a value and convert it back to within rounding error.
  • Converting a value and converting it back returns the original within your stated precision.
  • You can state the base unit each category converts through.

One hint, available after you have made a real attempt.

word counter

warmup ~30 min

Count words in a string or file and report the total.

What to implement

  • Count words in a supplied string.
  • Decide and document what counts as a word separator.
  • Handle empty input and repeated whitespace.
  • Report both total words and total characters.
  • Read the text from a file as well as from a string.

Done when

  • Multiple consecutive spaces do not inflate the count.
  • You can state your definition of a word and defend it.
  • An empty file reports zero rather than crashing.
  • The counting logic is a function that never reads a file itself.

One hint, available after you have made a real attempt.

frequency counter

core ~45 min

Count how often each word appears and report the most common ones.

What to implement

  • Build a mapping from word to count.
  • Normalise case so `The` and `the` are the same word.
  • Strip punctuation from word edges.
  • Print the top N words in descending order.
  • Handle a tie in counts deterministically and say what rule you chose.

Done when

  • The counts are correct on text containing punctuation and mixed case.
  • You can explain why a dictionary is the right structure here.
  • Running it twice on the same input produces the same ordering.
  • The top-N logic is separate from the counting logic.

One hint, available after you have made a real attempt.

password rule checker

core ~60 min

Validate a password against a set of rules and report every failure, not just the first.

What to implement

  • Check minimum length, and presence of upper, lower, digit and symbol.
  • Return all failed rules, not the first one.
  • Each rule is its own function.
  • The checker returns data; the caller does the printing.
  • Report the rules that passed as well as the ones that failed.

Done when

  • A password failing three rules reports three failures.
  • Adding a new rule requires no change to existing rules.
  • Each rule function can be tested on its own with no other rule involved.
  • An empty password reports every failure rather than one.

One hint, available after you have made a real attempt.

CSV summarizer

core ~90 min

Read a CSV and report per-column summaries without using pandas.

What to implement

  • Read the file using the standard library only.
  • Report row count and column names.
  • Compute min, max and mean for numeric columns.
  • Skip or report rows that do not parse, without crashing.
  • Report how many rows were skipped and why, rather than dropping them silently.

Done when

  • A file with a malformed row produces a warning, not a traceback.
  • The summary is correct on a file you did not write.
  • A column of mixed text and numbers is reported as text, not averaged.
  • The summary states the row count it actually used.

One hint, available after you have made a real attempt.

JSON reader/writer

core ~60 min

Round-trip structured data to disk as JSON and back.

What to implement

  • Write a nested structure to a JSON file.
  • Read it back and confirm it is equal to the original.
  • Handle the file not existing on first run.
  • Handle the file existing but containing invalid JSON.
  • Write to a temporary file and replace the original only once writing succeeded.

Done when

  • Running the program twice in a row works, first run included.
  • Corrupting the file by hand produces a clear message.
  • An interrupted write leaves the previous file intact.
  • Reading a structure and writing it back produces an equal structure, not merely a similar one.

One hint, available after you have made a real attempt.

simple menu-driven CLI

core ~60 min

A looping menu that dispatches to functions and exits cleanly — the skeleton of the Expense CLI.

What to implement

  • Display options and read a choice in a loop.
  • Dispatch each choice to its own function.
  • Handle an invalid choice without exiting.
  • Provide an explicit exit that leaves the loop.
  • Keep every menu action in its own module-level function rather than inside the loop.

Done when

  • Invalid input never crashes or exits the program.
  • Adding a menu entry means adding a function and one mapping entry.
  • The loop body is short enough to read in one screen.
  • Every action can be called directly from a test, bypassing the menu.

One hint, available after you have made a real attempt.

basic classes

core ~60 min

Model a transaction as a class and justify why it beats a dictionary here.

What to implement

  • Define a class with an initialiser and at least one method.
  • Create several instances and use them.
  • Add a readable string representation.
  • Write down why this is a class rather than a dict.
  • Add one method that derives a value rather than storing it.

Done when

  • Printing an instance produces something useful rather than an object address.
  • You can defend the choice of class over dictionary in two sentences.
  • No caller reaches into the instance to recompute something the class should own.
  • You can list which fields belong to the instance and which to the class.

One hint, available after you have made a real attempt.

tests

core ~90 min

Write pytest tests that would actually fail if the behaviour regressed.

What to implement

  • Test at least three functions from earlier drills.
  • Include one test for a failure case, not only the happy path.
  • Break the implementation deliberately and confirm the test fails.
  • Fix it and confirm the test passes again.
  • Give each test a name that states the behaviour rather than the function.

Done when

  • You have watched each test fail for the right reason.
  • The suite runs with a single command from the project root.
  • A stranger could read the test names and know what the code guarantees.
  • No test depends on another test having run first.

One hint, available after you have made a real attempt.

Stage project

Only milestones owned by Stage 1 count here

P1 · Stage project

Expense CLI

Project detail

P1.M1 · Personal Expense CLI

Resources

0% progress weight

Resource status is a convenience marker only. It cannot change competencies, gates, or stage completion — in any tier below.

Start here

PRIMARY

CS50's Introduction to Programming with Python

Harvard

The teaching path for this stage, assuming no prior programming. Follow it in order and do the problem sets before the drills, which are the same material at a different angle.

References

1 available
  • REFERENCEThe Python Tutorial Python Software FoundationThe official language tutorial. Use it to check exactly how a construct behaves rather than as a course — it assumes some prior programming, which is why it is a reference here and not the teaching path.The official Python Tutorial assumes some prior programming knowledge, so use it as reference while CS50P provides the beginner teaching path.Open
Need another explanation?5 supplementary resources · not part of the canonical library

Use these for a demonstrated gap, not as a parallel course. They are authored additions and can never be the primary resource for a subject.

  • REFERENCEgittutorial git-scm.comThe official introduction to the eight commands Stage 1 actually uses, and nothing beyond them. Pro Git is the Stage 2 resource; this is the smaller reference for saving and publishing work while you are still learning Python.Open
  • REFERENCEAutomate the Boring Stuff with Python Al SweigartFree full text, strongest on files, CSV and JSON — the exact material behind the Expense CLI. Use it as a second explanation when CS50P moves too fast.Open
  • REFERENCEpytest documentation pytestThe reference for the testing tool the stage requires. Read 'Get Started' and 'How-to guides'; skip the plugin ecosystem entirely for now.Open
  • REFERENCEPEP 8 — Style Guide for Python Code Python Software FoundationThe conventions every Python codebase assumes. Relevant the moment your code is read by someone else — which Stage 2 makes real.Open
  • REFERENCEThe Python Standard Library Python Software FoundationCheck here before installing anything. The source's framework rule is to prefer the standard library while it is educationally useful.Open

Stage gate

Readiness assessment

Not ready

Stage-specific requirements

Answer each prompt without notes. Expand a question only when you are ready to check your answer.
0/10
  • Implement a 150–300 line CLI application from a blank file
    Without asking AI to write it.
    Answer

    This is a demonstration, not a question. A complete one is a CLI of roughly 150–300 lines written from an empty file: it reads input, validates it, dispatches to functions in more than one module, persists data to disk, handles the missing and malformed file cases, and has tests you have watched fail. If you reached for generated code at any point, the demonstration has not happened yet.

  • Explain mutable vs immutable
    Answer

    A mutable object can be changed in place after it is created; an immutable one cannot, so any change produces a new object. Lists, dictionaries and sets are mutable; strings, integers and tuples are immutable. It matters when a value is shared: passing a mutable object into a function lets that function change what the caller still holds, while passing an immutable one cannot.

  • Explain list vs tuple vs set vs dict
    Answer

    A list is an ordered, mutable sequence that allows duplicates. A tuple is the same shape but immutable, which is why it can be used as a dictionary key. A set is unordered and holds each value once, making membership tests cheap. A dictionary maps keys to values and gives near-constant lookup by key. Choose from the question you ask most: order, uniqueness, or lookup by key.

  • Explain function arguments/returns
    Answer

    Arguments are the values a function receives; the return value is the single result it hands back. A function that prints has produced output but returned nothing, so nothing can be tested or reused. Returning a value lets the caller decide what to do with it, which is what makes the function composable and testable.

  • Explain exceptions
    Answer

    An exception is a signal that normal execution cannot continue, raised at the point the problem is detected and handled somewhere up the call stack. Catch the specific exception you anticipated and let the rest propagate, because a bare catch-all hides bugs. Validation prevents a bad state; exception handling responds to one that has already occurred.

  • Explain module/import
    Answer

    A module is a single Python file; a package is a directory of modules. Importing executes the target module once and binds its names into the importing namespace. Whether an import resolves depends on where Python believes the project root is, which is why the same code can import successfully from one directory and fail from another.

  • Explain class/object
    Answer

    A class is a template describing what data an instance holds and what it can do. An object is one instance made from that template, with its own attribute values. Reach for a class when data and behaviour travel together; a plain dictionary is still the right answer when there is no behaviour to attach.

  • Explain file serialization
    Answer

    Serialization converts in-memory objects into a form that can be written to disk, and deserialization reads it back. JSON preserves structure and basic types; CSV is text with conventions and returns every field as a string. Both need the missing-file and malformed-content cases handled, because both will occur.

  • Explain test vs runtime code
    Answer

    Runtime code is what the program does; test code is what proves it does it. Tests are not shipped as behaviour, they are run to check behaviour, and they must be able to fail. A test you have never watched fail is evidence of nothing, which is why you break the implementation deliberately before trusting a green run.

  • Explain what a commit records, and why `.gitignore` exists
    Basic Git only. Branching, merging and recovery belong to Stage 2.
    Answer

    A commit records a snapshot of the tracked files plus who made it, when, and why. `.gitignore` lists paths Git should not track, such as virtual environments, caches and anything holding a secret. It exists because the repository should contain the source of your project and nothing that can be regenerated or must never be shared, and because history keeps whatever you commit even after a later commit deletes it.

Universal requirements

The eight conditions 01_LEARNING_RULES.md applies to every stage. Expand one to see what it actually asks for.
0/8
  • Core concepts can be explained from memory.
    What this asks for

    Every subject in this stage has review questions. The condition is met when you can answer them out loud, without notes and without looking anything up, in your own words rather than a recited definition. An explanation you can only give with the material open is recognition, not recall.

  • Required exercises are complete.
    What this asks for

    Complete means each exercise satisfies its stated requirements and its done-when criteria, not that you attempted it. Where an exercise says you should be able to explain or defend something, that explanation is part of completing it. A stage whose source lists no exercises meets this through its owned project milestone instead.

  • Stage project works.
    What this asks for

    Works means it runs end to end from a clean checkout, on the inputs it was built for, with the failure cases it claims to handle actually handled. It is not a notebook that produced a result once. Someone else following your README should be able to run it without asking you a question.

  • Tests or verification exist.
    What this asks for

    There is something that would fail if the behaviour regressed, and you have watched it fail. That can be automated tests or a written verification procedure with recorded results, depending on what the stage produces. A test that has only ever passed is evidence of nothing.

  • README explains decisions.
    What this asks for

    The README says what the project is, how to install, run and test it, and why it is built the way it is: the choices you made, the alternatives you rejected, and what you deliberately left out. A list of commands with no reasoning does not meet this condition.

  • You can reproduce the core implementation without copying.
    What this asks for

    Delete the central piece and write it again from an empty file, without your previous version, a tutorial, or generated code in front of you. It does not have to be identical, it has to work and you have to be able to explain every line. This is the condition that separates having finished from being able.

  • You pass the stage self-assessment at >= 80%.
    What this asks for

    Record a gate exam and score yourself honestly against the dimensions the roadmap defines: recall, implementation, debugging, testing and design judgment. Elapsed time, hours watched and completed resources count for nothing here. Checking the boxes without a recorded exam does not open the gate.

  • Claude/ChatGPT reviewer finds no foundational blocker.
    What this asks for

    Ask an AI reviewer to examine the work against this stage's concepts and report foundational misunderstandings, not style. A foundational blocker is a misconception that later stages would build on, such as leakage, a broken abstraction, or an explanation that is confidently wrong. Nothing in that class may remain open when you pass.

Recorded exam

No exam recorded. Checking every requirement is not sufficient.

Evidence

Artifacts linked to this stage

Add evidence
No stage evidence yet.