Quiz#
This quiz covers the key concepts from Lecture 4: Function Fundamentals,
including function definition and calling, arguments (positional, default,
keyword, *args, **kwargs), scopes (LEGB), pass-by-assignment,
type hints, docstrings, and recursion.
Note
Instructions:
Answer all questions to the best of your ability.
Multiple choice questions have exactly one correct answer.
True/False questions require you to determine if the statement is correct.
Essay questions require short written responses (2-4 sentences).
Click the dropdown after each question to reveal the answer.
Multiple Choice#
Question 1
What is the output of the following code?
def greet(name, greeting="Hello"):
return f"{greeting}, {name}!"
print(greet("Alice"))
"Hello, Alice!""Alice, Hello!"TypeError"None, Alice!"
Answer
A – "Hello, Alice!"
The greeting parameter has a default value of "Hello". Since only name is provided, the default is used.
Question 2
What is the output of the following code?
def add_item(item, items=[]):
items.append(item)
return items
print(add_item("a"))
print(add_item("b"))
['a']then['b']['a']then['a', 'b']['a', 'b']then['a', 'b']TypeError
Answer
B – ['a'] then ['a', 'b']
This is the mutable default argument trap. The default list [] is created once when the function is defined and shared across all calls. Each call appends to the same list object.
Question 3
What does the *args parameter collect?
All keyword arguments as a dictionary.
All positional arguments as a tuple.
All arguments as a list.
Only the first extra argument.
Answer
B – All positional arguments as a tuple.
*args collects any extra positional arguments into a tuple. Keyword arguments are collected by **kwargs into a dictionary.
Question 4
What is the output of the following code?
x = 10
def modify():
x = 20
print(x)
modify()
print(x)
20then2020then1010then10UnboundLocalError
Answer
B – 20 then 10
The x = 20 inside modify() creates a local variable that shadows the global x. The global x remains 10.
Question 5
In the LEGB rule, what does the “E” stand for?
External
Enclosing
Environment
Evaluated
Answer
B – Enclosing
LEGB stands for Local, Enclosing, Global, Built-in. The enclosing scope refers to the scope of an outer function when using nested functions.
Question 6
What is the output of the following code?
def func(a: int, b: str) -> bool:
return str(a) == b
result = func(42, "42")
print(result)
TrueFalseTypeError"42"
Answer
A – True
Type hints are not enforced at runtime. str(42) returns "42", which equals the second argument "42", so the function returns True.
Question 7
What happens when you pass a list to a function and the function appends an element to it?
The original list is unchanged because Python uses pass-by-value.
The original list is modified because lists are mutable and passed by assignment.
The original list is replaced with a new list.
A
TypeErroris raised.
Answer
B – The original list is modified because lists are mutable and passed by assignment.
Python passes a reference to the list object. Since lists are mutable, in-place operations like append() modify the original object.
Question 8
What is the output of the following code?
def outer():
count = 0
def inner():
nonlocal count
count += 1
return count
return inner()
print(outer())
01NameErrorNone
Answer
B – 1
nonlocal count allows inner() to modify count in the enclosing scope. It increments from 0 to 1, and outer() returns the result of inner().
Question 9
What is the output of the following code?
def combine(*args, **kwargs):
return (args, kwargs)
print(combine(1, 2, x=3, y=4))
([1, 2], {'x': 3, 'y': 4})((1, 2), {'x': 3, 'y': 4})(1, 2, 3, 4)TypeError
Answer
B – ((1, 2), {'x': 3, 'y': 4})
*args collects positional arguments 1, 2 as a tuple, and **kwargs collects keyword arguments as a dictionary.
Question 10
Which of the following is NOT true about Python type hints?
They improve code readability and documentation.
They are enforced at runtime by the Python interpreter.
They enable static analysis tools like
mypy.They can specify
Optionalfor values that may beNone.
Answer
B – They are enforced at runtime by the Python interpreter.
Type hints are not enforced at runtime. They serve as documentation and enable static analysis tools like mypy, but Python ignores them during execution.
Question 11
What is the output of the following code?
def factorial(n):
if n <= 1:
return 1
return n * factorial(n - 1)
print(factorial(5))
515120RecursionError
Answer
C – 120
factorial(5) = 5 * 4 * 3 * 2 * 1 = 120. Each recursive call reduces n by 1 until the base case n <= 1 returns 1.
Question 12
What is the output of the following code?
def modify(data):
data = [99, 99, 99]
original = [1, 2, 3]
modify(original)
print(original)
[99, 99, 99][1, 2, 3][]None
Answer
B – [1, 2, 3]
Reassigning data = [99, 99, 99] inside the function creates a new local binding. The original list referenced by original is not affected because reassignment does not mutate the object.
Question 13
What does a function return if it has no return statement?
0An empty string
""NoneIt raises an error.
Answer
C – None
Functions without an explicit return statement (or with a bare return) implicitly return None.
Question 14
Which correctly unpacks a function’s return value?
def get_coords():
return 3.5, 7.2
x, y = get_coords()(x, y) = get_coords()Both A and B are correct.
Neither A nor B is correct.
Answer
C – Both A and B are correct.
Python supports tuple unpacking with or without parentheses. get_coords() returns a tuple, and both syntaxes correctly unpack the two values.
Question 15
What is the correct order of parameters in a function signature?
def func(*args, a, b, **kwargs):def func(a, b, *args, **kwargs):def func(**kwargs, a, b, *args):def func(a, **kwargs, b, *args):
Answer
B – def func(a, b, *args, **kwargs):
The correct order is: positional parameters, then *args for extra positional arguments, then **kwargs for extra keyword arguments.
True or False#
Question 16
True or False: In Python, a function can return multiple values as a tuple.
Answer
True
Python functions can return multiple values separated by commas, which are automatically packed into a tuple. The caller can unpack them using tuple unpacking.
Question 17
True or False: Default argument values are evaluated once when the function is defined, not each time it is called.
Answer
True
Default values are evaluated once at function definition time. This is why mutable defaults (like lists or dictionaries) can cause unexpected behavior across multiple calls.
Question 18
True or False: The global keyword allows a function to create a new global variable that did not exist before.
Answer
True
The global keyword can both modify an existing global variable and create a new one if it does not already exist in the module scope.
Question 19
True or False: **kwargs collects extra keyword arguments into a list.
Answer
False
**kwargs collects extra keyword arguments into a dictionary, not a list. Each keyword becomes a key, and its argument becomes the corresponding value.
Question 20
True or False: A recursive function without a base case will run forever without error.
Answer
False
Python has a maximum recursion depth (default 1000). A recursive function without a base case will hit this limit and raise a RecursionError, not run forever.
Question 21
True or False: Type hints in Python are enforced at runtime by the interpreter.
Answer
False
Type hints are not enforced at runtime. They are metadata used by developers, IDEs, and static analysis tools like mypy for type checking.
Question 22
True or False: In the LEGB rule, Python checks the local scope before the global scope.
Answer
True
The LEGB order is Local, Enclosing, Global, Built-in. Python checks the local scope first, so a local variable will shadow a global variable with the same name.
Question 23
True or False: Reassigning a parameter inside a function always modifies the original variable outside the function.
Answer
False
Reassigning a parameter inside a function creates a new local binding and does not affect the original variable. Only in-place mutations on mutable objects affect the original.
Question 24
True or False: A Google-style docstring should include a description, an Args section, and a Returns section.
Answer
True
A Google-style docstring includes a one-line description of the function, an Args section listing each parameter and its type/description, and a Returns section describing the return value.
Question 25
True or False: The nonlocal keyword is used to modify a variable in the enclosing function’s scope.
Answer
True
The nonlocal keyword allows a nested (inner) function to modify a variable defined in the enclosing (outer) function’s scope, rather than creating a new local variable.
Essay Questions#
Question 26
Explain the LEGB rule in Python. Describe what each letter stands for and the order in which Python searches for a variable name.
(2-4 sentences)
Answer Guidelines
Key points to include:
LEGB stands for Local, Enclosing, Global, Built-in.
Local: variables defined inside the current function.
Enclosing: variables in the scope of outer functions (for nested functions).
Global: variables defined at the module level.
Built-in: names in Python’s
builtinsmodule (e.g.,print,len,int).Python searches in this exact order and uses the first match found.
Question 27
Explain the difference between pass-by-assignment with mutable and immutable objects. Provide an example of each showing different behavior.
(2-4 sentences)
Answer Guidelines
Key points to include:
Python passes object references, not values or pointers.
Immutable objects (int, str, tuple): modifications inside a function create a new object; the original is unchanged. Example: adding to an integer parameter does not affect the caller’s variable.
Mutable objects (list, dict, set): in-place modifications (like
append()) affect the original object. Example: appending to a list parameter modifies the caller’s list.Reassignment inside a function always creates a new local binding, regardless of mutability.
Question 28
Explain the mutable default argument problem. Why is def func(items=[]) dangerous, and what is the recommended alternative?
(2-4 sentences)
Answer Guidelines
Key points to include:
Default argument values are evaluated once at function definition time, not at each call.
If the default is a mutable object (like a list or dict), all calls share the same object.
This causes unexpected accumulation of values across calls.
The fix is to use
Noneas the default and create a new object inside the function:if items is None: items = [].
Question 29
Describe the two essential components of a recursive function. What happens if one of them is missing?
(2-4 sentences)
Answer Guidelines
Key points to include:
A recursive function needs a base case (the stopping condition) and a recursive case (where the function calls itself with a simpler input).
Without a base case, the function will recurse indefinitely until Python raises a
RecursionError(default depth limit of 1000).Without a recursive case, the function is just a regular function with no recursion.
Example: factorial uses
n <= 1as the base case andn * factorial(n - 1)as the recursive case.
Question 30
Explain why type hints are useful even though Python does not enforce them at runtime. Give at least two benefits.
(2-4 sentences)
Answer Guidelines
Key points to include:
Type hints improve readability by making function signatures self-documenting.
They enable static analysis tools like
mypyto catch type errors before runtime.IDEs use them for autocompletion and better code navigation.
They make refactoring safer by surfacing type mismatches across the codebase.
They serve as documentation that stays in sync with the code (unlike comments that may become outdated).