Home Uncategorized Python Fundamentals – Variables, Data Types, Control Flow,...
Uncategorized

Python Fundamentals – Variables, Data Types, Control Flow, Loops: 20 Coding Interview Questions

Python fundamentals are the foundation for every data professional. Master variables, data types, control flow, and functions to solve any coding problem. These concepts appear in every interview and real-world code.

Variables and Dynamic Typing

Assignment & Reference Semantics: Python uses reference semantics: x = y makes x point to same object as y, not copy. Mutable objects (lists, dicts) share references: both point to same memory. Immutable objects (int, str, tuple) create new objects on reassignment. Understanding this prevents bugs: modifying y after x = y modifies y only if mutable.

x = 5
y = x
y = 10
print(x) # 5 (immutable int, x unchanged)
list1 = [1, 2, 3]
list2 = list1
list2.append(4)
print(list1) # [1, 2, 3, 4] (mutable list, both changed)

Mutable vs Immutable Objects: Immutable: int, float, str, tuple, frozenset. Once created, cannot change. Reassignment creates new object. Hashable: can be dict keys, set members. Mutable: list, dict, set. Modifiable after creation. Not hashable: cannot be dict keys. This distinction affects performance and correctness: immutable suitable for caching, mutable for collections.

immutable_tuple = (1, 2, 3)
immutable_str = “hello”
mutable_list = [1, 2, 3]
mutable_dict = {“a”: 1}
my_set = {immutable_tuple, immutable_str} # Works
my_dict = {immutable_tuple: “value”} # Works
my_set = {mutable_list} # TypeError: unhashable

Data Types Essentials: int (unlimited precision), float (64-bit), bool (True/False, subclass of int), str (immutable sequences), list (mutable sequences), tuple (immutable sequences), dict (key-value pairs), set (unique unordered). Type conversion: int(), str(), list(), etc. type() returns type, isinstance() checks type. Numbers: + – * / // % ** operations.

x = 10
y = 3
print(x // y, x % y, x ** y)
str_val = “123”
int_val = int(str_val)
my_list = [1, 2, 3]
my_tuple = tuple(my_list)
my_set = {1, 2, 2} # {1, 2} auto-dedup
print(type(x), isinstance(x, int))

Control Flow: Conditional Execution: if/elif/else branches based conditions. Truthiness: 0, empty ([], “”, {}, set()), None are falsy. Python evaluates left-to-right. Short-circuit evaluation: “a and b” stops if a is falsy. “a or b” stops if a is truthy. Ternary: x if condition else y. Exception handling: try-except-finally manages errors gracefully.

age = 25
if age >= 18:
print(“Adult”)
elif age >= 13:
print(“Teen”)
else:
print(“Child”)
status = “active” if age >= 18 else “inactive”
try:
x = int(“abc”)
except ValueError:
x = 0
finally:
print(“Done”)

Loops: Iteration Patterns: for loops over sequences (list, tuple, str, range, dict). range(n) generates 0 to n-1. enumerate() adds index. zip() pairs elements from sequences. while loops repeat until condition false. break exits loop, continue skips iteration. List comprehensions: [expr for item in seq if condition] create filtered lists efficiently. Generator expressions: (expr for item in seq) return iterators (lazy evaluation, memory-efficient).

for i in range(5):
print(i)
for idx, val in enumerate([“a”, “b”, “c”]):
print(idx, val)
for x, y in zip([1, 2], [3, 4]):
print(x, y)
i = 0
while i < 5: print(i) i += 1 squares = [x**2 for x in range(5)] even_gen = (x for x in range(100) if x % 2 == 0)

Functions & Advanced Concepts: def keyword defines function. return exits with value. *args: variable positional arguments (tuple). **kwargs: variable keyword arguments (dict). Unpacking: *seq unpacks sequences, **dict unpacks dictionaries. lambda: anonymous function. map(func, seq), filter(condition, seq) apply functions to sequences.

def greet(name, greeting=”Hello”):
return f”{greeting}, {name}!”
def sum_all(*args):
return sum(args)
def print_config(**kwargs):
for key, val in kwargs.items():
print(f”{key}={val}”)
a, b, *rest = [1, 2, 3, 4]
print(greet(“Alice”))
print(sum_all(1, 2, 3))
print_config(host=”localhost”, port=8080)
result = list(map(lambda x: x**2, [1, 2, 3]))

5 Complete Solved Coding Problems

Question 1: Floyd’s Cycle Detection (O(1) Space)

Find duplicate in list of n integers (1 to n-1). Must solve in O(1) extra space, O(n) time. Treat list as linked list: each value points to index.

def find_duplicate(nums):
slow = fast = nums[0]
while True:
slow = nums[slow]
fast = nums[nums[fast]]
if slow == fast:
break
slow = nums[0]
while slow != fast:
slow = nums[slow]
fast = nums[fast]
return slow
print(find_duplicate([1, 3, 4, 2, 2])) # 2
print(find_duplicate([3, 1, 3, 4, 2])) # 3

Explanation: Two pointers: slow moves 1 step, fast 2 steps. When they meet, cycle exists (duplicate). Second pass finds entry point. Floyd’s algorithm: elegant cycle detection, constant space, no set/dict needed.

Google – Senior SWE

Question 2: Mutable Default Arguments Pitfall

Why does function with list default create persistent state? How to fix safely?

def append_item_wrong(item, items=[]):
items.append(item)
return items
print(append_item_wrong(1)) # [1]
print(append_item_wrong(2)) # [1, 2] (same list!)
def append_item_right(item, items=None):
if items is None:
items = []
items.append(item)
return items
print(append_item_right(1)) # [1]
print(append_item_right(2)) # [2] (new list)

Explanation: Default arguments evaluated once at function definition, not each call. Mutable defaults (list, dict) shared across calls. Bug: modifications persist. Fix: use None as default, create new list inside function. Safe pattern.

Meta – Software Engineer

Question 3: Generator vs List Memory (O(1) vs O(n))

Create 1M integers. Compare memory: list [x for x in range(1M)] vs generator (x for x in range(1M)). Explain difference.

import sys
list_comp = [x for x in range(1000000)]
print(f”List memory: {sys.getsizeof(list_comp) / 1024 / 1024:.2f} MB”) # ~42 MB
gen_exp = (x for x in range(1000000))
print(f”Generator memory: {sys.getsizeof(gen_exp) / 1024:.2f} KB”) # ~0.05 MB
for val in gen_exp:
if val > 5:
break

Explanation: List stores all 1M values in memory (42MB). Generator computes values lazily on-demand (constant memory). Use list when you need random access, generator for large data/streaming. Generator 800x more memory-efficient here.

Amazon – Senior SWE

Question 4: Unpacking with *args/**kwargs

Function accepts variable arguments. Unpack list and dict to function call. Return combined result.

def calculate(a, b, c, multiplier=1):
return (a + b + c) * multiplier
args = [1, 2, 3]
kwargs = {“multiplier”: 2}
result = calculate(*args, **kwargs)
print(result) # (1+2+3)*2 = 12
def flexible(*args, **kwargs):
total = sum(args)
for key, val in kwargs.items():
print(f”{key}={val}”)
return total
print(flexible(1, 2, 3, name=”test”, value=10)) # 6

Explanation: *args unpacks list as positional arguments. **kwargs unpacks dict as keyword arguments. Enables flexible function signatures. Essential for decorators, wrappers, callbacks.

Apple – Software Engineer

Question 5: List/Dict Comprehension with Filtering

Count word frequencies in text. Filter words length > 3. Use dict comprehension. Result: {word: count}.

text = “the quick brown fox jumps over the lazy dog”
words = text.split()
from collections import Counter
freq = Counter(words)
filtered = {word: count for word, count in freq.items() if len(word) > 3}
print(filtered) # {‘quick’: 1, ‘brown’: 1, ‘jumps’: 1, …}
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares) # [0, 4, 16, 36, 64]

Explanation: Comprehensions combine filtering and transformation in one expression. More readable than loop. Faster execution (C-level). Dict comprehension creates filtered dicts. Essential for data manipulation.

Microsoft – Senior SWE

15 Practice Questions (Test Your Understanding)

Question 6: Calculate mean, median, mode using *args. Single function for any number of values.

Question 7: Flatten nested list [[1, 2], [3, [4, 5]]] recursively. Return single-level [1, 2, 3, 4, 5].

Question 8: Function accepting both *args and **kwargs. Parse each type separately, combine results.

Question 9: Validate password: min 8 chars, uppercase, lowercase, digit, special. Return detailed feedback (missing requirements).

Question 10: Fibonacci generator yielding infinite sequence. Use yield statement, test with next().

Question 11: Rotate list left by k positions. [1,2,3,4,5] rotated 2 → [3,4,5,1,2]. No built-in rotate().

Question 12: Create dict from two lists: keys from list1, values from list2. Use zip().

Question 13: Check Armstrong number (narcissistic): sum of digits^n equals number. n = digit count.

Question 14: Two-sum problem: find two numbers in list summing to target. Return indices. O(n) time.

Question 15: Decorator counting function calls. Store count, reset method. @counter applied to any function.

Question 16: Convert number to base k. Recursive approach. Result: string representation.

Question 17: Longest common substring of two strings. Return substring, not just length.

Question 18: Check if two strings are anagrams. Ignore case, spaces. Return True/False.

Question 19: Remove duplicates from list preserving order. Cannot use set (loses order).

Question 20: Prefix sum array: [1,2,3,4] → [1,3,6,10]. Efficient O(n) solution.

Master Python Fundamentals

Get our comprehensive Data Analytics: Ace All The Interview Concepts course.

Scroll to Top