← Home · Tutorial 02 · Foundations

Python fundamentals for AI

The small set of Python ideas that almost every AI program is built from.

Last reviewed 5 October 2026 · Written with AI assistance and reviewed by me

Where I learned this: my notes from DeepLearning.AI's AI Python for Beginners, taught by Andrew Ng. It covers variables and f-strings, loops, dictionaries, lists and conditionals, functions, files, packages and API calls. The classes section is from my own extra notes. The examples are my own, written in my own words, so go to the course for the original lessons. The code samples on this page were run to check their output, except the two API calls, which need your own key.

1Purpose first: why basics?

Before the syntax, the reason these matter.

When I started learning AI, I went back to Python fundamentals first. It is not glamorous, but almost every AI tutorial assumes you already know these basics and skips past them.

You do not need them to use a chatbot. You need them to read what an AI system is doing, and to ask sharper questions about it. Most AI code is a small set of plain Python ideas wired together.

Common mix-up: none of this is AI-specific syntax. It is ordinary Python. What makes it "AI fundamentals" is that chatbots, agents and retrieval systems are all built from these same pieces.

2The map

Which Python idea does which job.

Each Python idea has a job inside an AI program. Keep this map in mind and the rest of the page is just detail.

Python ideaIts job in an AI program
Variables and f-stringsBuilding a prompt with the user's question, a document or an instruction dropped in
DictionariesThe shape of every request and response, for example {"role": "user", "content": "..."}
ListsConversation history, search results, a batch of documents
For loopsDoing the same step for every document, result or message
if / elseRouting: answer or escalate, retry or stop, valid or invalid
Functions that returnReusable steps you can chain into a pipeline
FilesLoading documents in, saving results out
Imports and packagesUsing libraries and splitting your own code into files
Classes and objectsAgents, retrievers and chains in most frameworks
The API callThe one line that actually talks to the model
How they stack up
Datastrings, dicts, lists
→
Logicloops, if/else, functions
→
Structurefiles, imports, classes
→
API callthe model

3Variables and f-strings

How prompts get built.

A variable holds a value, and Python needs no type declaration. Names are case sensitive. An f-string (a string starting with f) lets you put variables and even calculations straight inside the text.

This is exactly how prompts get built: a template with the moving parts dropped in.

Python
flavor = "mango"
customer = "Asha"
n = 3
print(f"Hi {customer}, you ordered {n} scoops of {flavor}. Total: {n * 40} rupees.")
Output
Hi Asha, you ordered 3 scoops of mango. Total: 120 rupees.

Useful helpers while you are at it: type() tells you what a value is, len() counts characters or items (handy for checking how much text you are about to send), and round() tidies numbers. A string in triple quotes can span several lines, which is how long system prompts are usually written.

4Dictionaries

The shape of every request and response.

A dictionary stores key and value pairs inside curly braces. You look a value up by its key. Every request you send to a language model and every response you get back is built from dictionaries, so this is the single most useful idea on the page.

Python
message = {"role": "user", "content": "Where is my order?"}
print(message["role"], "->", message["content"])
print(list(message.keys()))
print(list(message.values()))
Output
user -> Where is my order?
['role', 'content']
['user', 'Where is my order?']

.keys() gives you the field names and .values() gives you the contents. A dictionary value can itself be a list or another dictionary, which is why a model response can look deeply nested.

Why it matters: if dictionaries feel unfamiliar, the whole shape of AI code will feel unfamiliar, because it is dictionaries from top to bottom.

5Lists and loops

Conversations, results and batches.

A list is an ordered collection. It can hold any type, including dictionaries. A for loop repeats an action for each item, and Python uses indentation to mark what is inside the loop.

A conversation history is a list of dictionaries. So are search results and a batch of documents to process.

Python
history = [
    {"role": "user", "content": "Hi"},
    {"role": "assistant", "content": "Hello! How can I help?"},
    {"role": "user", "content": "Where is my order?"},
]
history.append({"role": "assistant", "content": "Let me check that for you."})
print(len(history))
for turn in history:
    print(f"{turn['role']:>9}: {turn['content']}")
Output
4
     user: Hi
assistant: Hello! How can I help?
     user: Where is my order?
assistant: Let me check that for you.

You will meet one error early and often: asking for an item that is not there.

Python
print(history[10])
# IndexError: list index out of range
Where this bites: looping over search results that came back shorter than you expected. Check the length first, or loop instead of indexing by hand.

6if / else

Routing logic.

if and else run one path or another depending on a condition. Under every polished AI framework, decisions such as "escalate or answer", "confidence above the threshold or not" and "did it pass validation" are this exact statement.

Python
def route(task):
    if task["time_to_complete"] <= 5:
        return "do it now"
    else:
        return "escalate"

print(route({"time_to_complete": 3}), route({"time_to_complete": 20}))
Output
do it now escalate

Comparisons you will use constantly: ==, !=, <, <=, in (is this value in that list?), and and / or to combine them.

7Functions that return

Reusable, chainable steps.

A function is a named block of code. The key distinction is between a function that only prints and one that returns a value. A returned value can be passed into the next step. A printed one is a dead end.

Python
def shout_print(t):
    print(t.upper())

def shout_return(t):
    return t.upper()

a = shout_print("hello")   # prints HELLO, but a is None
b = shout_return("hello")  # b now holds "HELLO"
print(a, b)
Output
HELLO
None HELLO
Why it matters: wrap a model call in a function that returns its answer and you can chain it with other steps, instead of testing it once in a notebook and moving on. That is the difference between a demo and a pipeline.

8Files

Loading in and saving out.

Most retrieval systems start by loading documents, and most systems that produce something end by saving it. The pattern is open, read or write, close. The with block closes the file for you, even if something fails halfway.

Python
with open("notes.txt", "w") as f:      # "w" = write (creates or overwrites)
    f.write("Ticket 1: refund\n")

with open("notes.txt") as f:           # default mode is read
    text = f.read()
print(text)

Write mode "w" replaces an existing file, so use "a" (append) when you want to add to it instead.

9Imports and packages

How real projects are organised.

Real programs are not one script. You import code from other files you wrote, from Python's standard library, and from third-party packages installed with pip.

Terminal
pip install pandas beautifulsoup4
Python
import json                      # standard library, nothing to install
import pandas as pd            # third party, tables of data
from my_helpers import clean   # your own file, my_helpers.py

Two packages come up often in AI work: pandas for structured data and BeautifulSoup for pulling text out of web pages. The AI libraries themselves, for example the model providers' own packages, are installed the same way.

10Classes and objects

Agents and retrievers are objects.

A class bundles data and behaviour together. An object is one instance of a class. Inside a class, self means "this particular object". Almost every AI framework hands you objects: an agent, a retriever, a chain.

Python
class Agent:
    def __init__(self, name):
        self.name = name
        self.memory = []          # state this agent carries around

    def run(self, question):
        self.memory.append(question)
        return f"{self.name} has seen {len(self.memory)} question(s)"

bot = Agent("SupportBot")
print(bot.run("Where is my order?"))
print(bot.run("Can I change my address?"))
Output
SupportBot has seen 1 question(s)
SupportBot has seen 2 question(s)

You do not need to design class hierarchies to start. You do need to read self.memory or agent.run() and understand that the object remembers something and does something.

11The API call

Where everything points.

Everything above leads to one call: send a list of messages to a model and read back its reply. Frameworks such as LangGraph and LlamaIndex wrap this call. Learn it directly first and the frameworks stop feeling like magic.

Python (Anthropic Messages API)
# pip install anthropic
from anthropic import Anthropic

client = Anthropic()   # reads your key from the ANTHROPIC_API_KEY environment variable

response = client.messages.create(
    model="MODEL_ID_FROM_THE_DOCS",
    max_tokens=300,
    messages=[{"role": "user", "content": "Explain a Python dictionary in one sentence."}],
)
print(response.content[0].text)
Python (OpenAI chat completions)
# pip install openai
from openai import OpenAI

client = OpenAI()      # reads OPENAI_API_KEY from the environment

response = client.chat.completions.create(
    model="MODEL_ID_FROM_THE_DOCS",
    messages=[{"role": "user", "content": "Explain a Python dictionary in one sentence."}],
)
print(response.choices[0].message.content)

Look at what is in it: a model name, a list of dictionaries, and a reply you dig out of a nested structure. Every earlier section shows up in these few lines.

Things that change: model names are retired and replaced often, so copy a current one from the provider's documentation instead of reusing an old tutorial's. OpenAI also has a newer Responses API alongside chat completions. The idea, messages in and text out, stays the same.
Keep your key out of your code. Set it as an environment variable, never paste it into a script, and never commit it to a repository.

12A small pipeline

Every idea in one script.

Here is every earlier idea in one small script. A stand-in function plays the model, so you can run it without an account. It sorts support tickets, checks the answer is allowed, and saves the results.

Python
import json

def fake_llm(text):                      # stand-in for a real model call
    t = text.lower()
    if "refund" in t or "invoice" in t: return "Billing"
    if "error" in t or "crash" in t:    return "Technical"
    return "General"

tickets = ["I need a refund", "The app shows an error", "What are your hours?"]
allowed = {"Billing", "Technical", "General"}

results = []
for t in tickets:                        # loop over a list
    label = fake_llm(t)                  # function that returns
    if label not in allowed:             # if/else check
        label = "General"
    results.append({"ticket": t, "category": label})   # dictionaries in a list

with open("triage.json", "w") as f:      # write to a file
    json.dump(results, f, indent=2)
print(open("triage.json").read())
Output
[
  {
    "ticket": "I need a refund",
    "category": "Billing"
  },
  {
    "ticket": "The app shows an error",
    "category": "Technical"
  },
  {
    "ticket": "What are your hours?",
    "category": "General"
  }
]
Next step: replace fake_llm with a real model call from the previous section. The loop, the check and the file stay exactly as they are. That is the point of building from small pieces.

13Check yourself

Short questions and one line to remember.

Why is a function that returns more useful than one that prints?

A returned value can be passed to the next step. A printed value is only shown on screen, so nothing else can use it.

What shape is a message sent to a chat model?

A dictionary such as {"role": "user", "content": "..."}, and the full conversation is a list of those dictionaries.

What does self mean inside a class?

The particular object the method is running on, so self.memory is that object's own memory.

Where should an API key live?

In an environment variable or a secrets manager, never in the code and never in a repository.

One line to remember: "An AI program is mostly dictionaries in lists, looped over, checked with if/else, and sent through one API call."
Try it yourself: extend the ticket script with a fourth category and a ticket that should land in it. Then add a ticket the stand-in function cannot classify and confirm it falls back to General.
Notes based on lessons from DeepLearning.AI’s AI Python for Beginners by Andrew Ng. Python is open source and documented at docs.python.org. Examples and wording are my own. Independent notes, not affiliated with or endorsed by DeepLearning.AI or any company named here.