In short
Copy-pasting the same ten lines into five notebook cells is how bugs multiply. A function lets you write that logic once, name it, test it and reuse it everywhere.
Reusable blocks of logic with parameters, default values, *args/**kwargs and return values — how you'll structure every data pipeline and model utility.

Think of it like this
The mixer grinder
Drop in coconut, chillies and salt, press the button, get chutney. You don't care how the blades spin. Change the inputs to tomato and garlic and the same machine gives a different chutney. Ingredients are arguments, the chutney is the return value.
Watch it happen
What happens when clean_name() is called
Top of the stack is coloured
1/5Your script starts running at the top level.
The big ideas
What you need to know
Inputs in, output out
Parameters go in the brackets, return sends a value back. A function without return gives back None.
Defaults keep calls short
def split(data, test_size=0.2) lets callers skip test_size unless they want something different.
*args and **kwargs
*args collects extra positional values into a tuple. **kwargs collects named ones into a dict. Libraries use them to pass options along.
Local stays local
Variables made inside a function disappear when it returns. That keeps functions from messing with each other.
See it in code
Walk through the code
1def normalise(scores, low=0, high=100):2 """Squeeze scores into the 0-1 range."""3 span = high - low4 return [(s - low) / span for s in scores]5 6def describe(*values, **options):7 rounding = options.get("digits", 2)8 avg = sum(values) / len(values)9 return round(avg, rounding)10 11print(normalise([50, 75, 100])) # [0.5, 0.75, 1.0]12print(normalise([5, 10], high=10)) # [0.5, 1.0]13print(describe(3, 4, 8, digits=1)) # 5.01/4low and high have defaults. The docstring explains the function in one line.
normalise is a mini version of what scikit-learn's MinMaxScaler does. describe shows how *args and **kwargs accept flexible inputs.
Save yourself the pain
Common mistakes
Oops
Using a list as a default, like def add(item, bucket=[]).
Do this instead
Use bucket=None and create the list inside. A default list is shared across every call and keeps growing.
Oops
Printing the result inside the function instead of returning it.
Do this instead
Return the value. Then the caller can print it, save it or pass it to the next step.
Your mission
Build a tiny stats toolkit
Quick check
A function has no return statement. What does calling it give you?
Go deeper
- 1Practice writing functions with type hints and docstrings.
- 2Learn the difference between positional, keyword, default and variadic arguments.
- 3Refactor a long script into small, testable functions.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.