Skip to content

6. Functions

Beginner · 9 min read

A function packages code you want to reuse under a name. Good functions do one thing and are easy to test.

6.1 Defining and calling

def count_words(text):
    """Return the number of words in `text`."""   # docstring: what the function does
    return len(text.split())                      # `return` sends a value back

n = count_words("retrieval augmented generation")
print(n)                                          # → 3

A function without return gives back None.

6.2 Default and keyword arguments

def build_prompt(question, system="Be concise.", lang="English"):
    return f"{system} Answer in {lang}. Q: {question}"

print(build_prompt("What is RAG?"))
# → Be concise. Answer in English. Q: What is RAG?
print(build_prompt("What is RAG?", lang="Hindi"))   # keyword argument: skip ones you don't need
# → Be concise. Answer in Hindi. Q: What is RAG?

Never use a mutable default

def add(item, items=[]) shares one list across every call. Use items=None and create the list inside the function: items = [] if items is None else items.

6.3 *args and **kwargs

def total(*numbers):               # *args: any number of positional arguments, as a tuple
    return sum(numbers)

print(total(1, 2, 3))              # → 6

def call_llm(prompt, **options):   # **kwargs: any keyword arguments, as a dict
    return f"{prompt} | {options}"

print(call_llm("Hi", temperature=0.2, max_tokens=100))
# → Hi | {'temperature': 0.2, 'max_tokens': 100}

settings = {"temperature": 0.7}
print(call_llm("Hi", **settings))  # ** unpacks a dict into keyword arguments
# → Hi | {'temperature': 0.7}

6.4 Returning several values

def split_name(full):
    first, _, last = full.partition(" ")   # partition splits once around " "
    return first, last                     # returns a tuple

first, last = split_name("Priyabrat Dalbehera")
print(last)                                # → Dalbehera

6.5 Scope

limit = 100                    # global: defined at the top level

def check(tokens):
    over = tokens - limit      # functions can READ globals…
    return over > 0            # …but `over` exists only inside this call

print(check(150))              # → True

Pass values in as arguments and return results, rather than changing globals — it keeps code testable.

6.6 lambda — tiny anonymous functions

chunks = [{"text": "a", "score": 0.4}, {"text": "b", "score": 0.9}]

best_first = sorted(chunks, key=lambda c: c["score"], reverse=True)   # sort by a field
print(best_first[0]["text"])                                          # → b

Use lambda only for short expressions like sort keys; give anything longer a proper def.

Why it matters for GenAI

Wrapping each step — load_docs(), chunk(), retrieve(), answer() — in its own function is what turns a notebook experiment into a pipeline you can test and reuse.

Practice

  • Write truncate(text, max_words=50) that returns the first max_words words joined back into a string.
Answer
def truncate(text, max_words=50):
    """Keep only the first `max_words` words."""
    return " ".join(text.split()[:max_words])

print(truncate("one two three four", max_words=2))   # → one two