Functions in Python: Practical Examples for Placement Prep
Functions in Python with examples: def keyword, arguments vs parameters, return values, recursion, *args/**kwargs, and the placement-test patterns interviewers reuse.
A Python function is a def block that takes inputs, runs a few lines of logic, and either prints output or returns a value the caller can use. That definition is short on purpose. Most placement-test questions on functions test whether you know the difference between prints and returns, what happens when you pass a list, and how recursion unwinds. The rest of this article walks through the four function shapes you actually need, the interview gotchas, and a few worked examples of the kind FACE Prep sees repeated across campus drives.
What a function is, in one paragraph
A function is a named, reusable block of code. You write it once with def, you call it as many times as you like, and you pass values in through parentheses. The two things a function can do at the end are: return a value (which the caller can store) or finish without return (in which case it implicitly returns None). The official Python docs on defining functions cover the syntax in detail; the version you need for a placement test is the one below.
def add(a, b):
return a + b
result = add(5, 3)
print(result) # 8
Three things to notice. The def keyword starts the definition. The body is indented (PEP 8 says four spaces; see the PEP 8 naming and spacing rules). And the function only runs when you call it on the line add(5, 3), not when Python reads the def line.
Why functions exist at all
Without a function, the same five lines of code get copied wherever you need them. Edit the logic in one place, forget the other three, and the bug only shows up in production. Functions remove that drift. They are also the unit interviewers ask you to write. Almost no campus coding round asks for a script; almost all of them ask for a function with a defined signature.
The four argument shapes you actually need
Most Python tutorials list six or seven argument styles. For a placement test you need four. Here they are in one table.
| Shape | Looks like | Use when |
|---|---|---|
| Positional | def f(a, b) | Caller knows the order. Most common. |
| Keyword with default | def f(a, b=10) | One argument has a sensible fallback. |
Variable positional (*args) | def f(*nums) | Caller passes any count of values. |
Variable keyword (**kwargs) | def f(**opts) | Caller passes any set of named options. |
A worked example with all four:
def order_pizza(size, crust="thin", *toppings, **extras):
print(f"size={size}, crust={crust}")
print(f"toppings={toppings}")
print(f"extras={extras}")
order_pizza("large", "stuffed", "olive", "corn", spice="medium", cheese=True)
That call prints size=large, crust=stuffed, toppings=('olive', 'corn'), extras={'spice': 'medium', 'cheese': True}. The order of the four shapes in the signature is fixed: positional, then default, then *args, then **kwargs. Swap the order and Python raises SyntaxError at definition time.
Arguments vs parameters
The two words get used interchangeably in college labs, but interviewers care about the distinction.
- Parameters are the names inside the parentheses on the
defline. Indef add(a, b),aandbare parameters. - Arguments are the actual values you pass on the call line. In
add(5, 3),5and3are arguments.
A common viva question: “Can a parameter have the same name as a variable in the calling scope?” Yes. The parameter shadows the outer variable inside the function only, and the outer variable is unaffected.
Return values, including the None you didn’t write
Three rules cover almost every return-related test question.
- A function with no
returnstatement returnsNone. Callingprint(f())on such a function showsNone. - A function can have multiple
returnstatements. The first one hit ends the function, and anything below it never runs. This is “early return”, and it is the cleanest way to handle edge cases. - A function can return multiple values, comma-separated. Python packs them into a tuple, which you can unpack on the calling line.
def divide(a, b):
if b == 0:
return None, "division by zero"
return a / b, "ok"
value, status = divide(10, 4)
print(value, status) # 2.5 ok
The divide function above also doubles as the standard pattern for “return a result and an error” in Python code that does not use exceptions.
Print vs return — the placement-test trap
The two are not interchangeable. print writes to the screen and is useful for debugging. return hands the value back so you can do something with it. The trap is a function that prints its result and then is used in an expression:
def square_print(n):
print(n * n)
x = square_print(4) # prints 16
print(x + 1) # TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
x is None, because square_print never returned anything. This MCQ shows up in TCS NQT and Cocubes-style coding rounds in slightly different shapes every season.
Pass-by-reference, the mutable-default trap, and other gotchas
Strictly, Python is pass-by-object-reference (sometimes called pass-by-assignment). The legacy “call by reference” phrasing in older textbooks is a half-truth. The function receives a reference to the same object the caller holds. Mutate that object and the caller sees the change. Rebind the name inside the function and the caller does not.
def append_one(lst):
lst.append(1) # mutates — caller sees this
def reassign(lst):
lst = [99] # rebinds local name — caller does not see this
a = [10, 20]
append_one(a)
print(a) # [10, 20, 1]
reassign(a)
print(a) # [10, 20, 1] — unchanged
The mutable-default-argument trap
This is the single most-asked gotcha in Python placement tests. Look at this code and predict the output:
- Q: What does the second call print?
- Code:
def add_item(x, bag=[]): bag.append(x) return bag print(add_item("apple")) print(add_item("banana")) - Answer: First call prints
['apple']. Second call prints['apple', 'banana']. - Why: Python evaluates the default value
[]once at function-definition time, not on every call. Both calls share the same list. - Fix: Use
Noneas the sentinel and create a fresh list inside.def add_item(x, bag=None): if bag is None: bag = [] bag.append(x) return bag
This pattern is in the Python documentation’s footnote on default values; it surfaces in roughly one in three Python MCQ banks across Indian placement tests.
Recursion, in three lines
A recursive function calls itself with a smaller version of the problem and stops at a base case. Two examples cover most of what placement tests will ask.
- Factorial (
5 factorial = 120):def factorial(n): if n == 0: return 1 return n * factorial(n - 1) print(factorial(5)) # 120 - Fibonacci (the inefficient-but-classic recursive version):
def fib(n): if n < 2: return n return fib(n - 1) + fib(n - 2) print(fib(7)) # 13
Two interview points worth knowing. First, the base case is the only thing that stops the recursion, and forgetting it raises RecursionError. Second, naive recursive Fibonacci runs in exponential time because it recomputes the same values; a dict or functools.lru_cache brings it to linear. Recruiters ask the Fibonacci runtime question often; the answer they want is O(2^n) for the version above.
Practice patterns from FACE Prep’s placement-test bank
Three short worked examples to lock the concepts in. Each is the kind of question that surfaces in TCS NQT, Wipro Elite, or any Cocubes-driven aptitude round.
Predict-the-output #1
- Code:
def f(x, y=2, z=3): return x + y * z print(f(1)) print(f(1, z=10)) - Answer:
7and21. - Why: First call uses defaults:
1 + 2 * 3 = 7. Second call keepsy=2but overridesz=10:1 + 2 * 10 = 21. Operator precedence (*before+) matters.
Predict-the-output #2
- Code:
def swap(a, b): a, b = b, a return a, b x, y = 5, 9 swap(x, y) print(x, y) - Answer:
5 9. - Why: The function returns the swapped pair but the caller throws the return value away. Names
xandyin the outer scope are untouched. The fix:x, y = swap(x, y).
Predict-the-output #3
- Code:
def grow(n, lst=[]): lst.append(n) return lst print(grow(1)) print(grow(2)) print(grow(3, [])) print(grow(4)) - Answer:
[1],[1, 2],[3],[1, 2, 4]. - Why: Calls one, two, and four share the default list; call three passes its own. This is the mutable-default trap dressed as a four-line MCQ.
For a wider warm-up across Python basics (variables, loops, lists, strings), the curated set of Python practice programs covers the foundation these function questions sit on top of. If you want a slightly larger worked program to apply functions inside, the build a simple calculator in Python walkthrough wires four arithmetic functions behind a menu, and the greatest of three numbers and sum of array elements routines are the two most-asked function-as-a-utility questions in early-round placement tests.
From def add to def ask_llm
A working Python function takes inputs, runs logic, returns a value. So does an LLM API call. Once you can write def add(a, b): return a + b, the next step is def ask_llm(prompt): return client.complete(prompt). Same function shape, same return, same predict-the-output discipline applied to a different kind of black box. The mutable-default trap and the print-vs-return distinction matter just as much when the value being returned is a model response instead of a sum.
If you want to test that step at low cost before committing to a full course, TinkerLLM is the ₹299 sandbox where you write small Python wrappers around real model calls, see what the API actually returns, and break a few things on purpose. The recursion section above is the same loop you will write to chain a model call into its own next prompt; the four argument shapes are the same ones you will use to design a clean function signature for a tool-calling agent.
Primary sources
Frequently asked questions
What is the difference between an argument and a parameter in Python?
A parameter is the variable name written inside the parentheses when you define a function. An argument is the actual value you pass when you call it. In `def add(a, b)`, `a` and `b` are parameters; in `add(5, 3)`, `5` and `3` are arguments.
Can a Python function return more than one value?
Yes. Python returns multiple values as a tuple, and you can unpack them on the calling line. `return a + b, a - b` followed by `s, d = calc(5, 3)` gives you both results in one call.
What does it mean that Python is pass-by-reference?
Strictly, Python is pass-by-object-reference (sometimes called pass-by-assignment). The function receives a reference to the same object the caller has. Mutating that object (e.g., appending to a list) is visible outside; rebinding the name inside the function is not.
When should I use *args and **kwargs?
Use `*args` when the function accepts a variable number of positional arguments (e.g., a `sum_all` that takes any count of numbers). Use `**kwargs` when it accepts arbitrary keyword arguments — common in wrapper functions that forward options to another call.
What is the mutable default argument trap?
Writing `def add_item(x, lst=[])` shares one list across every call that omits `lst`, because Python evaluates the default once at definition time. The fix is `def add_item(x, lst=None): lst = lst or []`. This is a standard placement-test MCQ.
How is return different from print inside a function?
`print` writes to the screen and the function still returns `None`. `return` hands a value back to the caller, where it can be stored in a variable, used in an expression, or chained into another call. Interviews almost always want `return`, not `print`.
A self-paced playground for building with LLMs.
TinkerLLM is FACE Prep's sister property. A guided environment for shipping real LLM applications, the kind of project that earns a paragraph on your resume, not a line.
Try TinkerLLM (₹299 launch)