Lambda functions, modules, I/O operations and memory management are fundamental Python concepts that are commonly covered in interviews. Understanding these topics helps you write efficient Python programs and answer both theoretical and coding-based interview questions confidently.
1. What are modules and packages in Python? What is __name__ == "__main__" used for?
A module is a Python file (.py) that contains code such as functions, classes and variables. A package is a collection of related modules organized inside a directory, typically containing an __init__.py file.
import math
from datetime import date
if __name__ == "__main__" is used to check whether a Python file is being run directly or imported into another file. Code inside this block executes only when the file is run directly and is skipped when the file is imported as a module.
2. What is a namespace in Python?
A namespace is a collection of names and their associated objects. Python uses namespaces to organize variables, functions and classes, helping prevent naming conflicts when the same name is used in different parts of a program.

Types of Namespaces:
- Built-in Namespace: Contains built-in functions and exceptions such as print(), len(), and int().
- Global Namespace: Contains names defined at the module level.
- Local Namespace: Contains names defined inside a function. A new local namespace is created whenever a function is called.
x = "global"
def outer():
y = "enclosing"
def inner():
z = "local"
print("x:", x)
print("y:", y)
print("z:", z)
inner()
outer()
Output
x: global y: enclosing z: local
Explanation:
- x belongs to the global namespace, y belongs to the enclosing scope of outer() and z belongs to the local namespace of inner().
- Python searches for names following the LEGB (Local -> Enclosing -> Global -> Built-in) rule.
3. What is Python’s memory model? How does reference counting work?
Python uses automatic memory management, which means memory is allocated and released automatically without requiring manual intervention from the programmer. Every object in Python has:
- Type: Specifies the kind of object (such as int, str, or list).
- Value: actual data stored in the object.
- Reference count: number of references pointing to the object.
Python manages memory primarily through reference counting and garbage collection.
1. Reference Counting: Each object keeps track of how many references point to it. When the reference count becomes zero, Python automatically frees the memory occupied by that object.
a = [1, 2, 3]
b = a
del a
Explanation:
- The list object is initially referenced by a. Assigning b = a creates another reference to the same object.
- del a removes one reference. The object remains in memory because b still refers to it.
2. Garbage Collection (GC): Reference counting cannot remove objects involved in circular references. To handle such cases, Python uses a Garbage Collector (GC) that identifies and removes unused objects.
4. What does the nonlocal keyword do in Python?
nonlocal keyword is used inside a nested function to modify a variable defined in its enclosing (outer) function. It tells Python that the variable should not be treated as local to the nested function.
Without nonlocal, assigning a value to the variable inside the nested function would create a new local variable instead of modifying the existing one.
def outer():
x = 10
def inner():
nonlocal x
x += 5
print("Inner:", x)
inner()
print("Outer:", x)
outer()
Output
Inner: 15 Outer: 15
Explanation:
- x is defined in the outer() function. The nonlocal x statement allows inner() to modify that variable.
- After increasing x by 5, the updated value is visible in both inner() and outer().
- Without nonlocal, Python would treat x inside inner() as a separate local variable and raise an error when attempting x += 5.
5. What is a lambda function?
lambda function is a small anonymous function created using the lambda keyword. It can accept any number of arguments but can contain only a single expression, whose result is automatically returned.
Lambda functions are commonly used for simple operations that do not require a full function definition using def.
s = "GeeksforGeeks"
res = lambda text: text.upper()
print(res(s))
Output
GEEKSFORGEEKS
6. How are lambda functions used with map(), filter() and reduce()? Give examples.
Using map(): applies a function to every element in an iterable and returns the transformed values.
nums = [1, 2, 3, 4]
res = list(map(lambda x: x**2, nums))
print(res)
Output
[1, 4, 9, 16]
Using filter(): selects only those elements for which the given function returns True.
nums = [1, 2, 3, 4, 5]
res = list(filter(lambda x: x % 2 == 0, nums))
print(res)
Output
[2, 4]
Using reduce(): applies a function cumulatively to the elements of an iterable and returns a single result.
from functools import reduce
nums = [2, 4, 6, 2, 8, 5]
res = reduce(lambda x, y: x + y, nums)
print(res)
Output
27
7. How can lambda functions be used with sorted()? Explain with example.
sorted() function provides a key parameter that determines how elements should be compared during sorting. A lambda function is commonly used as the key to define custom sorting logic directly within the sorted() call.
Example 1: Sort Strings by Length
words = ["apple", "bat", "banana"]
res = sorted(words, key=lambda x: len(x))
print(res)
Output
['bat', 'apple', 'banana']
Example 2: Sort Tuples by the Second Element
pairs = [(1, 3), (2, 1), (4, 2)]
res = sorted(pairs, key=lambda x: x[1])
print(res)
Output
[(2, 1), (4, 2), (1, 3)]
8. Can lambda functions return multiple values? Explain with an example.
Yes, a lambda function can return multiple values by returning them as a tuple, list, or another collection. Although a lambda function can contain only a single expression, that expression can produce multiple values.
f = lambda x, y: (x + y, x * y)
res = f(3, 4)
print(res)
Output
(7, 12)
Explanation: lambda function takes two arguments, x and y. It returns a tuple containing two values: x + y -> 7 and x * y -> 12
Note: Lambda functions are best suited for simple expressions. If the logic requires multiple statements or becomes complex, a regular function defined with def is usually a better choice.
9. How does Python handle variable scope and closures?
Python uses the LEGB rule to determine where a variable should be searched.
- Local (L): Variables defined inside the current function.
- Enclosing (E): Variables defined in the enclosing function of a nested function.
- Global (G): Variables defined at the module level.
- Built-in (B): Names provided by Python, such as print(), len() and sum().
A closure is created when a nested function accesses variables from its enclosing scope and retains those values even after the outer function has finished executing.
def outer(x):
def inner(y):
return x + y
return inner
closure_func = outer(10)
print(closure_func(5))
Output
15
Explanation:
- outer(10) creates a function where x is 10. The nested function inner() uses x from the enclosing scope.
- Even after outer() finishes execution, inner() remembers the value of x.
- Therefore, closure_func(5) returns 10 + 5, which is 15.