Beginner22 min

Functions and arguments

Package logic into reusable, testable units — the unit of work in every data pipeline and LLM wrapper.

Why this matters in AI / ML / GenAI

Chunking, embedding, prompt building, scoring, and metric computation are all functions. Once logic lives in a function you can unit-test it, reuse it in a notebook and a FastAPI service, and change one place instead of ten.

Defining and calling

def name(parameters): starts a function. The indented block is its body. return sends a value back; a function with no return returns None.

Parameters vs arguments: parameters are the names in the definition, arguments are the values you pass.

Keep functions small and single-purpose. clean_text, chunk_document, build_prompt — three functions beat one process() that does everything, because you can test each one.

Defaults, keywords, and *args / **kwargs

Default values make optional settings readable: def summarize(text, max_words=50):.

Never use a mutable default (def f(items=[])). The list is created once and shared across calls — a genuinely nasty bug. Use items=None and build inside.

Keyword arguments at the call site self-document: generate(prompt, temperature=0.2, max_tokens=256). In LLM code this matters, because generate(p, 0.2, 256) is unreadable.

*args collects extra positional arguments into a tuple; **kwargs collects extra keyword arguments into a dict. LLM SDK wrappers use **kwargs to pass provider-specific options through.

Scope and returning multiple values

Names created inside a function are local — they disappear when it returns. Reading a global is allowed; rebinding one requires global, which you should almost always avoid.

Return several values as a tuple: return mean, std, then mean, std = stats(values). For more than three, return a dict or a dataclass (covered later) so callers are not guessing positions.

Copy-paste examples

Copy into your own editor, or load one into the compiler below and press Run.

A prompt builder function

Defaults + keyword arguments make the call site readable.

def build_prompt(question, context="", style="concise"):
    header = f"Answer in a {style} style."
    if context:
        return f"{header}\n\nContext:\n{context}\n\nQuestion: {question}"
    return f"{header}\n\nQuestion: {question}"

print(build_prompt("What is RAG?"))
print("=====")
print(build_prompt("What is RAG?", context="RAG retrieves then generates.", style="detailed"))

The mutable default argument trap

Run this. The first function keeps growing across calls — that is the bug.

def broken(item, bucket=[]):
    bucket.append(item)
    return bucket

def fixed(item, bucket=None):
    if bucket is None:
        bucket = []
    bucket.append(item)
    return bucket

print("broken:", broken("a"), broken("b"), broken("c"))
print("fixed :", fixed("a"), fixed("b"), fixed("c"))

Return multiple values and pass through kwargs

**kwargs is how thin LLM wrappers forward provider options.

def score_stats(scores):
    mean = sum(scores) / len(scores)
    worst = min(scores)
    return mean, worst

mean, worst = score_stats([0.91, 0.72, 0.85])
print(f"mean={mean:.3f} worst={worst:.2f}")

def call_model(prompt, **kwargs):
    options = {"temperature": 0.2, **kwargs}
    return {"prompt": prompt[:20], "options": options}

print(call_model("Explain embeddings", max_tokens=128, temperature=0.0))

Write a text chunker

Try it — in-browser Python

Change chunk_size to 30 and watch the number of chunks change.

Output

Python runs in your browser. First run downloads the runtime.

Press Run (or Ctrl+Enter) to execute.

CPython in WebAssembly. Stdlib works. NumPy and pandas load on demand. No input(), no GPU, no network installs.

Takeaways

  • Small single-purpose functions are testable and reusable across notebook and service.
  • Use keyword arguments for model options; never use a mutable default.
  • Return tuples for two values, dicts or dataclasses for more.