Session 1

  • Introduction
  • Development environment
  • Variables, I/O and data types
  • Making decisions

Learning outcomes

Learning outcomes: Introduction

You’ll be able to:

  • explain what programming is and why it matters for AI/ML
  • explain why Python is the language of choice
  • describe the course structure: units and sessions
  • find help when stuck: documentation, help(), the internet, AI tutors

Learning outcomes: Development environment

You’ll be able to:

  • setup a development environment with Jupyter
  • explain what a virtual environment is and activate it
  • install a Python package
  • explain what the Python interpreter is and use it interactively and to run scripts
  • create and use a Jupyter Notebook: code and Markdown cells, kernel

Learning outcomes: Variables, I/O and data types

You’ll be able to:

  • store and load data of different types in variables
  • retrieve and display information
  • convert data between types
  • perform operations with numeric types
  • format a string

Learning outcomes: Making decisions

You’ll be able to:

  • make decisions based on conditions
  • import a package and use its functions
  • load data from an Excel file
  • basic data filtering using boolean logic

Unit 0

Introduction

Introduction

  • Why learn to program?
  • Why Python?
  • Course overview
  • Learning resources

Why learn to program?

  • AI and ML are applied through code : every step from loading data, to training models and evaluating results is written in a programming language
  • Libraries are the real syllabus : scikit-learn, PyTorch, pandas… are what you’ll use; they have no graphical interface, only an API
  • Debugging is thinking : when a model underperforms, you need to inspect data, trace transformations, test assumptions; that process is also programming

What is programming?

The composition of sequences of instructions, called programs, that computers can follow to perform tasks. — Wikipedia

(and also design, testing, debugging, maintenance…)

The art of programming is the art of organizing complexity. — Edsger Dijkstra.

Any fool can write code that a computer can understand. Good programmers write code that humans can understand. — Martin Fowler

What about no-code, low-code and AI generated code?

  • No-code tools are built by programmers : when they break, hit a limit, or do something unexpected, you’re stuck
  • AI assistants write code, not decisions : AI can generate code in seconds, but you should still understand it, judge it, and know when it’s wrong
  • The interesting problems don’t have buttons : custom data, novel models, real deployments; at some point serious projects touch code
  • Go beyond just using tools : a postgrad in Applied AI/ML means understanding what’s happening under the hood, not just clicking “train model”

Low/no-code raises the floor. Code removes the ceiling.

Why Python?

  • The world runs AI and ML in Python : scikit-learn, PyTorch, TensorFlow, Hugging Face are all Python-first
  • Syntax similar to natural language : if value > threshold: reject reads like a decision, not a program; focus on ideas, not punctuation
  • Open source, free
  • One language, everything included — Python is not the best language for anything, but its a close second best for everything

Course Overview

U0 Introduction

U1 Development environment: uv, Jupyter, Anaconda

U2 Variables, I/O, data types and type conversion

U3 Making decisions: conditionals and boolean logic

U4 Lists and tuples: slicing, unpacking

U5 Loops and flow control

U6 Dictionaries and comprehensions

U7 Functions: scope, lambda, args

U8 map, filter and pandas masks

U9 Modules and packages

U10 Files: text, binary, JSON, pathlib

U11 Exceptions and tracebacks

U12 Intro to classes & OOP

U13 Debugging tools and methods

Sessions

Session Duration Units
1 2h U0 – U3
2 3h U4 – U7
3 3h U8 – U13

Each session opens with the learning outcomes of its units and closes with their recaps.

Learning Resources

Trying and failing , and trying again. Nothing beats experience.

Python has a help function. Type help(anything) and you can read documentation on it.

The internet is your friend. Search for errors and desired functionality. Stack Overflow is a solid resource.

Reading other people’s code is a great way to learn (if it’s good code)

AI may be good for learning - use the Socratic method.

Example of a recommended prompt

Act as my Socratic tutor on Python programming
  [or some other topic, e.g., UI building with Gradio, Async/Await, PyTorch].

- Never provide direct code solutions unless I ask for
  a specific syntax example.
- Ask one question at a time to guide me to the answer,
  starting with simple concepts and building up to complex ones.
- If I am stuck, offer a small hint or an analogy rather than the code.
- If I make a mistake, prompt me to run a test case or identify
  the contradiction in my reasoning.
- Wait for my input after every question."

Unit 1

Development environment

Development environment

  • Install Python and manage packages with uv
  • Install and launch JupyterLab
  • Use the Python interpreter and Jupyter Notebooks
  • Alternatives: Anaconda, SageMaker, Colab

Development environment

  • Python distribution
  • package manager
  • Jupyter Notebooks are very popular. We’ll install that to get you started.

uv

  • uv is increasingly becoming the standard way of installing Python and managing environments and packages
  • it works through the terminal (so go ahead and open a terminal, PowerShell, whatever you have in your system)
  • one tool replaces several: Python installer, pip, venv, …
  • fast: installs packages in seconds

uv install

macOS / Linux (Terminal):

curl -LsSf https://astral.sh/uv/install.sh | sh

Windows (PowerShell):

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

Close and reopen the terminal, then check it worked:

uv --version

More options in the uv installation docs.

Windows without admin rights, or the command is blocked? Follow this guide.

uv project

  • uv creates environments per project (by default)
  • in a new project folder, run uv init to initialize the project
    • this creates a few files for managing dependencies among other things
mkdir aaiml-python
cd aaiml-python
uv init
  • pyproject.toml – project description + list of dependencies
  • .python-version – which Python version the project uses
  • main.py, README.md – starter files
  • .venv/ and uv.lock appear after the first uv add / uv run

What is a virtual environment?

  • a virtual environment (venv) is a folder with its own Python and its own installed packages
  • uv creates one per project, in the .venv/ folder
  • projects don’t interfere with each other
    • project A can use pandas 2.x while project B stays on 1.x
    • installing a package in one project doesn’t change the others, nor the system’s Python
  • you don’t need to edit .venv/ by hand: uv manages it for you

Installing JupyterLab

uv add jupyterlab
  • downloads Python if needed, creates .venv, installs the package
  • the package is recorded in pyproject.toml

Start JupyterLab:

uv run jupyter lab
  • uv run runs a command inside the project environment
  • JupyterLab opens in your browser

Activating the virtual environment

uv run uses the project’s venv automatically. To type python or jupyter lab directly instead, activate the venv first (from the project folder):

macOS / Linux:

source .venv/bin/activate

Windows (PowerShell):

.venv\Scripts\activate
  • the terminal prompt now starts with (aaiml-python)
  • python, pip, jupyter lab now use the project’s venv
  • run deactivate to leave
  • PowerShell says “running scripts is disabled”? Skip activation and use uv run (details)

uv cheat sheet

Command What it does
uv init start a new project in the current folder
uv add <pkg> install a package and record it
uv remove <pkg> uninstall a package
uv run <cmd> run a command/script in the project env, e.g. uv run python main.py
uv sync recreate the env from pyproject.toml (e.g. on another computer)
uv tree show the project’s packages and what they depend on
uv python list show available/installed Python versions
source .venv/bin/activate activate the venv (Windows: .venv\Scripts\activate)

Tip: inside a notebook started with uv run jupyter lab, you can install packages with !uv add <pkg>.

The Python interpreter

  • the interpreter is the program that reads Python code and executes it, one statement at a time
  • interactive mode (REPL: read, evaluate, print, loop): type a line, get the result immediately
uv run python
>>> 2 + 3
5
>>> print("hello")
hello
>>> exit()
  • script mode: save code in a .py file and run the whole file
uv run python main.py

Jupyter Notebook

  • a notebook (.ipynb) mixes code, results, text and plots in one document
  • it runs on a kernel: a Python interpreter running in the background, which keeps variables in memory between cells
  • in JupyterLab: File → New → Notebook, choose the Python kernel
Cell type Contains Run it with
Code Python code; output appears below the cell Shift+Enter
Markdown formatted text: titles, lists, equations Shift+Enter
  • [3] next to a cell is the order it ran in; cells can run in any order, so the state may not match top-to-bottom reading
  • if things get confusing: Kernel → Restart Kernel and Run All Cells

uv vs Anaconda

You only need one of them.

  • uv: lightweight and fast, terminal-based, one environment per project; install only what you need
  • Anaconda: graphical installer, comes with Python, Jupyter and hundreds of data science packages pre-installed; much larger download

Prefer a graphical installer with everything bundled? Anaconda is the alternative.

Anaconda Distribution

Anaconda is a popular open-source Python distribution that makes it easy to install Python and many data science libraries.

This link will take you to the Anaconda download page. Download Anaconda for your operating system.

Easy to follow along videos for installing Anaconda in Windows and Mac.

Anaconda Download Verification

Amazon SageMaker

Amazon SageMaker provides an extensive set of tools to develop the complete lifecycle of a ML solution.

It provides a managed Jupyter Notebook service, i.e. running on remote servers (AWS).

Beware of running processes after no longer in use, because of associated costs. Small mistakes can cost a lot of money.

Google Colab

Another managed Jupyter Notebook provider is Google Colab.

Google Colab is a free Jupyter Notebook provider that will allow you to run code on Google’s servers, using only CPUs. Execution with GPUs is paid.

Getting Started

From now on, it’s assumed you have a functional Python environment.

Go on and open a Jupyter Notebook to follow along.

Unit 2

Variables, I/O and data types

Variables, I/O and data types

  • Create variables
  • Input/output information: print and input
  • Numeric types: int vs float, operations
  • Dealing with text - str: concatenation, formatting f"pi={3.1415}", string methods
  • Boolean type: True and False
  • Type conversion, e.g. float("3.14")

Variables

What is a Variable?

A variable is a placeholder for some value.

Think of it like a drawer where you can put anything you want and retrieve it later.

Creating Variables

Let’s create some variables.

accuracy = 0.87
num_samples = 1000
model_name = "LogisticRegression"
previous_accuracy = accuracy
accuracy = 0.91
print("Model trained!")
print(accuracy)
print(model_name)
print(accuracy, num_samples, previous_accuracy)

accuracy, num_samples and model_name are all variables.

Assignment Operator

accuracy = 0.87
num_samples = 1000
model_name = "LogisticRegression"
previous_accuracy = accuracy
accuracy = 0.91
print("Model trained!")
print(accuracy)
print(model_name)
print(accuracy, num_samples, previous_accuracy)

The = operator assigns a value (any value) to the variable.

Variable Assignment

accuracy = 0.87
num_samples = 1000
model_name = "LogisticRegression"
previous_accuracy = accuracy
accuracy = 0.91
print("Model trained!")
print(accuracy)
print(model_name)
print(accuracy, num_samples, previous_accuracy)

We can also assign the value of a variable to another variable.

previous_accuracy now has the value of accuracy, which is 0.87

Overwriting Variables

accuracy = 0.87
num_samples = 1000
model_name = "LogisticRegression"
previous_accuracy = accuracy
accuracy = 0.91
print("Model trained!")
print(accuracy)
print(model_name)
print(accuracy, num_samples, previous_accuracy)

And we can overwrite the value of an existing variable.

The value of accuracy is now 0.91 instead of 0.87.

But previous_accuracy is still 0.87!

Retrieving Values

We can retrieve the value of a variable, simply by typing its name.

accuracy = 0.87
num_samples = 1000
model_name = "LogisticRegression"
previous_accuracy = accuracy
accuracy = 0.91
print("Model trained!")
print(accuracy)
print(model_name)
print(accuracy, num_samples, previous_accuracy)

We’re retrieving the value of accuracy and then assigning it to another variable.

Input/Output

How to interact with the outside of our program?

I/O Methods

  • Terminal (print)
  • Files (later)
  • Networking (not covered)
  • Graphical interfaces (not covered)
  • Inter-process communication (not covered)

Interacting through the terminal

  • print - send values to user
  • input - receive values from user

The print Function

print will write some text to the terminal/screen.

accuracy = 0.87
num_samples = 1000
model_name = "LogisticRegression"
previous_accuracy = accuracy
accuracy = 0.91
print("Model trained!")
print(accuracy)
print(model_name)
print(accuracy, num_samples, previous_accuracy)

The print function will comes in handy to check the values of variables.

If we feed it a non text value, it will try to convert it to text first.

Printing Multiple Values

accuracy = 0.87
num_samples = 1000
model_name = "LogisticRegression"
previous_accuracy = accuracy
accuracy = 0.91
print("Model trained!")
print(accuracy)
print(model_name)
print(accuracy, num_samples, previous_accuracy)

We can also print several values at once, if we separate them with commas.

The input Function

print("Enter patient glucose level (mg/dL):")
glucose = input()
age = input("Enter patient age: ")

After executing the input function, the terminal will wait for user input.

The user can write whatever she wishes, ending with an enter.

Input with a prompt

print("Enter patient glucose level (mg/dL):")
glucose = input()
age = input("Enter patient age: ")

The input function can receive an optional string that is printed to the terminal before receiving input from the user.

Data types

We’ve already seen some values of different kinds.

Do you remember which?

Numeric Types

train_split = 0.8
num_samples = 5000
print(type(train_split))   # float
print(type(num_samples))   # int
dataset_name = "diabetes"
print(type(dataset_name))  # str
is_balanced = False
print(type(is_balanced))   # bool

Both train_split and num_samples are numeric types, but they’re not the same.

The type Function

train_split = 0.8
num_samples = 5000
print(type(train_split))   # float
print(type(num_samples))   # int
dataset_name = "diabetes"
print(type(dataset_name))  # str
is_balanced = False
print(type(is_balanced))   # bool

The type function will tell us the type of any value we give it.

train_split is a float (as in floating point number), the representation of a real number.

num_samples is an int (as in integer), the representation a natural number including negative numbers.

String Type

str (short for string) is how we represent text.

train_split = 0.8
num_samples = 5000
print(type(train_split))   # float
print(type(num_samples))   # int
dataset_name = "diabetes"
print(type(dataset_name))  # str
is_balanced = False
print(type(is_balanced))   # bool

str is another basic type in Python.

It’s used to encode text like dataset names, column names, labels.

Boolean Type

bool (short for boolean) encodes a True or False value.

train_split = 0.8
num_samples = 5000
print(type(train_split))   # float
print(type(num_samples))   # int
dataset_name = "diabetes"
print(type(dataset_name))  # str
is_balanced = False
print(type(is_balanced))   # bool

Many operations, like comparisons between two values, will return a True or False value.

Numeric types

int, float

Operations: + - * / // % **

Conversion

💻 Let’s see in practice! 💻

String

How can we deal with text? Strings!

String methods

Formatted strings

Conversion

💻 Back to the code! 💻

Unit 3

Making decisions

Making decisions

  • Indentation
  • Making decisions: if / elif / else
  • Conditions: basics, boolean logic
  • and or vs. & |
  • import packages, e.g. import pandas

Indentation

In Python, indentation defines structure — there are no { } (like in C, for example)

if True:
    print("this is inside the block")   # indented = belongs to the if
    print("so is this")
print("this is outside")                # not indented = runs regardless

Use 4 spaces, or a consistent tab, per level. Mixing them causes errors.

Modern editors allow configuration and usually fix mixing.

Conditionals Example

Conditionals enable us to execute a portion of code based on some decision.

new_accuracy = 0.92
decision = None
if new_accuracy >= 0.9:
    decision = "deploy"
else:
    decision = "keep training"

What is happening here?

The if Statement

new_accuracy = 0.92
decision = None
if new_accuracy >= 0.9:
    decision = "deploy"
else:
    decision = "keep training"

In Python, we state conditionals with the if statement.

We’re checking if new_accuracy meets our deployment threshold of 0.9.

If it is, the comparison operator (>=) will return True, otherwise False.

Executing Conditional Code

new_accuracy = 0.92
decision = None
if new_accuracy >= 0.9:
    decision = "deploy"
else:
    decision = "keep training"

When the condition after if is True, the program will execute the code that is indented forward.

Here, that code is in line 4.

The else Statement

new_accuracy = 0.92
decision = None
if new_accuracy >= 0.9:
    decision = "deploy"
else:
    decision = "keep training"

The else statement allows us to define code to be executed when the condition fails.

Here, that code is in line 6.

Comparison Operators

Conditions are usually built by comparing values. The result is always a bool.

Operator Meaning Example Result
== equal to model_name == "LogisticRegression" True
!= not equal to num_samples != 1000 False
< less than 0.87 < 0.9 True
> greater than 0.87 > 0.9 False
<= less than or equal to num_samples <= 1000 True
>= greater than or equal to 0.92 >= 0.9 True

= assigns a value, == compares two values.

Chaining Conditions

new_accuracy = 0.88
champion_accuracy = 0.87
decision = None
if new_accuracy >= champion_accuracy + 0.02:
    decision = "deploy new model"
elif new_accuracy >= champion_accuracy - 0.01:
    decision = "retrain and monitor"
elif new_accuracy >= 0.80:
    decision = "collect more data"
else:
    # below minimum threshold
    decision = "discard model"

We can also chain several conditions with elif.

elif works like else, but it allows us to define more conditions.

Condition Order

new_accuracy = 0.88
champion_accuracy = 0.87
decision = None
if new_accuracy >= champion_accuracy + 0.02:
    decision = "deploy new model"
elif new_accuracy >= champion_accuracy - 0.01:
    decision = "retrain and monitor"
elif new_accuracy >= 0.80:
    decision = "collect more data"
else:
    # below minimum threshold
    decision = "discard model"

When chaining conditions in this way, a given condition is only processed if all the previous conditions fail.

Condition Processing Order

new_accuracy = 0.88
champion_accuracy = 0.87
decision = None
if new_accuracy >= champion_accuracy + 0.02:
    decision = "deploy new model"
elif new_accuracy >= champion_accuracy - 0.01:
    decision = "retrain and monitor"
elif new_accuracy >= 0.80:
    decision = "collect more data"
else:
    # below minimum threshold
    decision = "discard model"

The condition on line 6 will only be processed if the condition on line 5 fails.

Multiple elif Statements

new_accuracy = 0.88
champion_accuracy = 0.87
decision = None
if new_accuracy >= champion_accuracy + 0.02:
    decision = "deploy new model"
elif new_accuracy >= champion_accuracy - 0.01:
    decision = "retrain and monitor"
elif new_accuracy >= 0.80:
    decision = "collect more data"
else:
    # below minimum threshold
    decision = "discard model"

The condition on line 8 will only be processed if the conditions on lines 5 and 7 fail.

Final else Statement

new_accuracy = 0.88
champion_accuracy = 0.87
decision = None
if new_accuracy >= champion_accuracy + 0.02:
    decision = "deploy new model"
elif new_accuracy >= champion_accuracy - 0.01:
    decision = "retrain and monitor"
elif new_accuracy >= 0.80:
    decision = "collect more data"
else:
    # below minimum threshold
    decision = "discard model"

The final else statement will only be processed if the conditions on lines 5, 7 and 8 fail.

Comments

new_accuracy = 0.88
champion_accuracy = 0.87
decision = None
if new_accuracy >= champion_accuracy + 0.02:
    decision = "deploy new model"
elif new_accuracy >= champion_accuracy - 0.01:
    decision = "retrain and monitor"
elif new_accuracy >= 0.80:
    decision = "collect more data"
else:
    # below minimum threshold
    decision = "discard model"

# is the start of a comment in Python.

About Comments

Comments are not code, they’re just extra information the programmer adds to the program so it’s easier to understand the code.

Comments are never executed, even if they contain valid code.

Boolean logic

Combine conditions with:

a and b → result is True, if both arguments are True

a or b → result is True, if any of the arguments is True

not a → if a was True, it is now False, and vice versa.

Boolean logic example

patience = 15 # confit param

# these two variables would come from the
# current iteration of a training run
accuracy = 0.88
epoch = 30

# these two variables would come from the
# best past iteration of a training run
best_accuracy = 0.87
best_epoch = 24

decision = None
if accuracy < best_accuracy and epoch - best_epoch >= patience:
    decision = "stop training"
elif accuracy >= best_accuracy:
    # continue training
    best_accuracy = accuracy
    best_epoch = epoch
# there is no else in this example

Demo

  • Installing and importing packages
  • Quick teaser: filtering data in an Excel file with boolean logic
    • See animations for bitwise boolean logic in the following slides

Boolean logic - bitwise

Useful for filter masks.

Animations from Real Python

Recap

Recap: Development environment

  • Setup development environment
  • Python interpreter: interactive mode (>>>) and running scripts (uv run python main.py)
  • Create and use a Jupyter Notebook: code and Markdown cells, kernel, execution order
  • uv projects and virtual environments (.venv), activation
  • Inspect dependencies with uv tree
  • Install packages: uv add / pip install

Recap: Variables, I/O and data types

  • Create variables
  • Input/output information: print and input
  • Numeric types: int vs float, operations
  • Strings: "a string" and 'also a string', concatenation, formatting f"pi={3.1415}"
  • Boolean type: True and False
  • Type conversion, e.g. float("3.14")

Recap: Making decisions

  • Making decisions: if / elif / else
  • Conditions: basics, boolean logic
  • and or vs. & |
  • import packages to our programs, e.g. import pandas
  • Practical example: load tabular data from Excel, relative vs. absolute paths, boolean masks to filter a table
// multiplex-patch.js // Patches the reveal.js multiplex plugin to also broadcast: // - fragment navigation (fragmentshown / fragmenthidden) // - slide changes for headingless slides (re-emits slidechanged robustly) // // Only activates on the master (speaker view) — clients are unaffected. // Include in your Quarto frontmatter under revealjs.include-after-body // or revealjs.include-in-header (after the multiplex plugin loads). Reveal.on('ready', () => { const config = Reveal.getConfig().multiplex; // Only patch the master (speaker view has the secret) if (!config?.secret) return; const socket = io.connect(config.url); const broadcast = () => { socket.emit('multiplex-statechanged', { state: Reveal.getState(), // includes indexh, indexv, indexf, paused, overview secret: config.secret, socketId: config.id, }); }; Reveal.on('fragmentshown', broadcast); Reveal.on('fragmenthidden', broadcast); // Re-emit on slidechanged to catch headingless slides that the // stock plugin may miss due to index resolution timing Reveal.on('slidechanged', broadcast); });