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.
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 idea | Its job in an AI program |
|---|---|
| Variables and f-strings | Building a prompt with the user's question, a document or an instruction dropped in |
| Dictionaries | The shape of every request and response, for example {"role": "user", "content": "..."} |
| Lists | Conversation history, search results, a batch of documents |
| For loops | Doing the same step for every document, result or message |
| if / else | Routing: answer or escalate, retry or stop, valid or invalid |
| Functions that return | Reusable steps you can chain into a pipeline |
| Files | Loading documents in, saving results out |
| Imports and packages | Using libraries and splitting your own code into files |
| Classes and objects | Agents, retrievers and chains in most frameworks |
| The API call | The one line that actually talks to the 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.
flavor = "mango"
customer = "Asha"
n = 3
print(f"Hi {customer}, you ordered {n} scoops of {flavor}. Total: {n * 40} rupees.")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.
message = {"role": "user", "content": "Where is my order?"}
print(message["role"], "->", message["content"])
print(list(message.keys()))
print(list(message.values()))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.
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.
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']}")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.
print(history[10]) # IndexError: list index out of range
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.
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}))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.
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)HELLO None HELLO
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.
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.
pip install pandas beautifulsoup4
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.
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?"))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.
# 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)# 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.
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.
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())[
{
"ticket": "I need a refund",
"category": "Billing"
},
{
"ticket": "The app shows an error",
"category": "Technical"
},
{
"ticket": "What are your hours?",
"category": "General"
}
]
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.