Python for AI
The Python you actually need before any AI work: the language, the data libraries and the habits that stop a notebook turning into a mess.
Python installation, VS Code and Jupyter
Get a working setup once and stop fighting it. Every example in this course runs on Python 3.11 or newer.
- Install Python from python.org, or
brew install pythonon a Mac. On Windows tick “Add python.exe to PATH” in the installer – skipping it causes most of the “python is not recognised” problems. - Check it:
python --versionandpip --version. - VS Code plus the Python extension is enough for everything here. Jupyter notebooks are useful while you are exploring data; anything that has to run twice belongs in a
.pyfile. - Never install packages into the system Python – the virtual environment section below is not optional.
On a locked-down office laptop you may not get an installer approved. The Python compiler on this site runs in the browser with no installation at all, so you can still follow every lesson here while you wait for IT.
Variables, data types, operators and control statements
The bedrock. If you have written Java for Selenium, the ideas transfer – the syntax is shorter and indentation replaces braces.
- Indentation is the block. Four spaces, consistently – a stray tab is a real error, not a style opinion.
- f-strings (
f"{name}") are the readable way to build text. ==compares values,iscompares identity. Use==unless you are checkingNone.- Integer division is
//, true division is/;7 / 2gives 3.5.
risk_score = 0.87 # float
customer = "Priya" # str
is_blocked = False # bool
attempts = 3 # int
if risk_score > 0.9:
decision = "block"
elif risk_score > 0.6:
decision = "review"
else:
decision = "allow"
for attempt in range(attempts):
print(f"{customer}: attempt {attempt + 1} -> {decision}")
while attempts > 0:
attempts -= 1
print("done", attempts)▶ Try it yourselfThe threshold ladder above is exactly how a fraud or claim model is wired into an application. The model gives the score; code like this turns it into allow / review / block. Your test cases live on the boundaries – 0.6 and 0.9 – not in the model.
Lists, tuples, dictionaries and sets
Four containers that cover nearly everything. Picking the right one makes later code shorter.
- list when order matters and the contents change; tuple when they must not.
- dict is the workhorse – every JSON response you get back from an API arrives as one.
- set removes duplicates for free and makes “is it in there?” fast.
- List comprehensions replace most small loops and read better once you are used to them.
cases = ["login", "logout", "reset"] # list - ordered, changeable
limits = (200, 5000) # tuple - ordered, fixed
user = {"name": "Priya", "role": "member"} # dict - key -> value
seen = {"TC-01", "TC-02"} # set - unique, unordered
cases.append("register")
user["role"] = "admin"
seen.add("TC-01") # already there, set stays the same size
print(len(cases), user["name"], len(seen))
print([c.upper() for c in cases if c.startswith("l")]) # list comprehension▶ Try it yourselfReading an API response in a test: response["data"]["orders"][0]["status"] is dict, dict, list, dict. Knowing which container you are in at each step is most of what makes JSON assertions feel easy or painful.
Functions, modules, packages and exception handling
Where scripts turn into something you can reuse and test.
- Type hints (
age: int) are optional but make an editor catch mistakes before you run. - Raise an error for a broken input; return a value for a valid one. Do not return
Noneto mean failure. try / except / finally– catch the specific exception, never a bareexcept:.- A module is one
.pyfile; a package is a folder of them with an__init__.py.
def premium(age: int, cover: int, smoker: bool = False) -> float:
"""Published formula - the same one our InsureHub practice app uses."""
if age < 18 or cover <= 0:
raise ValueError("age must be 18+ and cover positive")
base = cover * 0.0022
loading = 1.6 if smoker else 1.0
return round(base * (1 + (age - 18) * 0.012) * loading, 2)
try:
print(premium(31, 500000))
print(premium(16, 500000))
except ValueError as err:
print("rejected:", err)
finally:
print("checked")▶ Try it yourselfThis is a published formula, so a tester can compute the expected premium independently and assert on it. That is the difference between a rule and a model: here you can say “this number is wrong”. Keep that distinction – it decides whether you write an assertion or a range check.
Object-oriented programming
Enough OOP to read the AI libraries and to structure your own tools. If you have used page objects, you already think this way.
__init__builds the object;selfis the instance.@propertyexposes a computed value as if it were an attribute.__repr__is what you see when you print the object – worth writing for anything you debug.- Inheritance exists, but prefer small classes that hold data and a few methods over deep hierarchies.
class Claim:
def __init__(self, claim_id: str, amount: float, documents: list):
self.claim_id = claim_id
self.amount = amount
self.documents = documents
@property
def is_complete(self) -> bool:
return len(self.documents) >= 3
def decide(self) -> str:
if not self.is_complete:
return "pending documents"
return "approved" if self.amount < 50000 else "manual review"
def __repr__(self):
return f"Claim({self.claim_id}, {self.amount})"
c = Claim("CL-1001", 42000, ["bill", "report", "id"])
print(c, c.is_complete, c.decide())The decision rule above is the one in our InsureHub practice app: under 50,000 with all three documents is auto-approved. Writing the business object this way means the same rules can be unit tested without a browser.
File handling, JSON, CSV and REST APIs
Getting data in and out. Most AI work is 20% model and 80% moving data around.
- Always use
with open(...)– it closes the file even when something throws. - Always pass
encoding="utf-8". Windows defaults to something else and breaks on Indian names and the rupee sign. requestsis friendlier thanurllibfor real work:pip install requests.- Set a timeout on every network call. A test that hangs forever is worse than one that fails.
import csv, json, urllib.request
# JSON file in and out
with open("cases.json", "w", encoding="utf-8") as fh:
json.dump([{"id": "TC-01", "title": "valid login"}], fh, indent=2)
with open("cases.json", encoding="utf-8") as fh:
cases = json.load(fh)
# CSV, one row at a time
with open("cases.csv", "w", newline="", encoding="utf-8") as fh:
writer = csv.DictWriter(fh, fieldnames=["id", "title"])
writer.writeheader()
writer.writerows(cases)
# a REST call with nothing but the standard library
req = urllib.request.Request("https://httpbin.org/json", headers={"Accept": "application/json"})
with urllib.request.urlopen(req, timeout=10) as resp:
data = json.loads(resp.read())
print(type(data), list(data)[:3])Module 7 calls an LLM API with this exact shape – a POST with a JSON body and a bearer token. If you can read and write JSON confidently, the “AI” part of calling a model is ten lines.
NumPy, Pandas and Matplotlib
The three libraries every dataset passes through. Pandas is the one you will use daily.
- NumPy is fast numeric arrays – the layer Pandas and every ML library sit on.
- Pandas gives you a DataFrame: a table with named columns, filters, grouping and joins.
df.head(),df.info(),df.describe()anddf.isna().sum()are the first four things to run on any new dataset.- Matplotlib draws the chart. One
df.plot()is usually enough to spot a problem that a table hides.
import pandas as pd
df = pd.DataFrame({
"policy": ["P1", "P2", "P3", "P4"],
"age": [24, 38, 51, 29],
"cover": [300000, 500000, 250000, 800000],
"claimed": [0, 1, 1, 0],
})
print(df.shape, list(df.columns))
print(df.describe()) # count, mean, min, max per column
print(df[df["cover"] > 400000]) # filter
print(df.groupby("claimed")["age"].mean()) # average age of claimers vs not
df["premium"] = (df["cover"] * 0.0022).round(2) # new column
print(df.head())Pandas is immediately useful to a tester even without AI: load a CSV export from the application and one from the database, join them on the id and print the rows that differ. That is a data-migration test that would take a day by hand.
Virtual environments, pip and Git basics
The habits that keep a project reproducible on someone else’s machine.
- One virtual environment per project. It is a folder you can delete and rebuild from
requirements.txt. - Commit
requirements.txt, never the.venvfolder. .envholds API keys and goes straight into.gitignore. A leaked key in Git history is a real incident, and rewriting history later is painful.- Commit small and often with a message that says why, not what.
python -m venv .venv # create an isolated environment source .venv/bin/activate # Windows: .venv\Scripts\activate pip install pandas requests pip freeze > requirements.txt # exact versions, committed to the repo git init echo ".venv/" >> .gitignore echo ".env" >> .gitignore # never commit API keys git add . && git commit -m "AI course: module 2"
When we cleaned the client’s three AI project ZIPs for this site, the work was exactly this: drop __pycache__, drop the local database that held personal history, keep requirements.txt. Anyone could then run them from a clean folder.
Project: analyse a dataset and generate a report
- Export any table from an application you test – orders, claims, tickets – as CSV. Twenty rows is enough to start.
- Load it with Pandas and print
shape,info(),describe()andisna().sum(). Write down three things that look wrong. - Group by one column and compute a mean or a count. State one sentence you could tell the business.
- Write the summary to a CSV and a chart to a PNG, then wrap the whole thing in a function so it runs on next month’s export too.