Navigate by Range
Python Full-Stack Interview Questions 21–25 (Duck Typing, Identity, Memory, with, Import)
This lesson answers five practical Python interview questions with simple, beginner-friendly explanations, real-world analogies, and runnable code examples that include expected output. Read slowly, try each example in your editor, and use the short lists to anchor the main ideas.
21. Explain duck typing in Python.
Duck typing is a style of dynamic typing where the suitability of an object is determined by the presence of methods and attributes, not by its explicit type. The classic phrase is: "If it walks like a duck and quacks like a duck, it's a duck." In practice, this means you write code that operates on objects that implement the expected behavior, rather than checking the object's class.
- Focus on the behavior (methods/attributes) an object provides.
- Avoid strict
isinstance()checks unless necessary; prefer duck-typed interfaces. - Duck typing encourages flexible, easier-to-test code, but careful error handling is important.
Example: a function that expects something that can be iterated and printed. It doesn't care about the concrete type.
def print_all_things(things):
"""
We only assume 'things' is iterable and its items are printable.
"""
for item in things:
print(item)
# Works for a list
print_all_things([1, 2, 3])
# Works for a generator
print_all_things(x * x for x in range(3))
# Works for a custom container that implements __iter__
class Bag:
def __init__(self, items):
self._items = list(items)
def __iter__(self):
return iter(self._items)
print_all_things(Bag(["apple", "banana"]))
Expected output when run:
# Output:
1
2
3
0
1
4
apple
banana 22. What is the difference between is and ==?
== checks for value equality - it asks "are these two objects equal in value?" is checks for identity - it asks "are these two names pointing to the exact same object in memory?" In everyday terms: == compares the contents written on two index cards; is checks whether both index cards are the very same physical card.
==calls the object's__eq__method (or falls back to identity if not implemented).ischecks whether the two operands share the same object id (id(a) == id(b)).- Use
==for value comparisons andisfor checkingNoneor singletons.
Examples showing both behaviors:
a = [1, 2, 3]
b = [1, 2, 3]
c = a
print(a == b) # True, same contents
print(a is b) # False, different objects
print(a is c) # True, same object
x = None
print(x is None) # True - use 'is' for None checks Expected output:
# Output:
True
False
True
True 23. How is memory allocated to variables in Python?
Python uses an object model with automatic memory management. Every value in Python is an object; variables are simply names (references) that point to objects. Memory allocation and reclaiming are handled by the Python runtime (the interpreter), primarily via reference counting plus a cyclic garbage collector to clean cycles.
- When you create a value (e.g.,
x = 1000), the interpreter allocates memory for a Python object representing that value. - Names (variables) hold references to objects; multiple names can reference the same object.
- Reference counting: when no references remain to an object, it's deallocated. Cyclic GC handles reference cycles (objects referencing each other).
Simple demonstration showing identities and shared references:
a = [1, 2, 3]
b = a # b references the same list object
c = a.copy() # c is a new list with the same contents
print(id(a)) # object id of a
print(id(b)) # same as a
print(id(c)) # different id
# Changing through one name affects the shared object:
b.append(4)
print(a) # [1, 2, 3, 4] Expected output (ids will differ on your machine; shown here as placeholders):
# Output (example):
140319123456320
140319123456320
140319123457088
[1, 2, 3, 4] Notes and interview tips:
- Be ready to explain reference vs copy (shallow vs deep) and when to use each.
- Understand that small integers and short strings may be interned (implementation detail); avoid relying on that behavior.
- Mention
gcmodule for manual inspection andsys.getrefcount()for reference counts (remembergetrefcountadds a temporary reference when called).
24. What is Python's with statement?
The with statement simplifies resource management by ensuring setup and teardown code runs reliably. It's commonly used for files, locks, and network connections. Objects used in a with block implement the context manager protocol - they provide __enter__ (setup) and __exit__ (cleanup) methods.
__enter__runs when entering the block and can return a helpful value.__exit__runs when exiting the block, even if an exception occurs; it can suppress exceptions when needed.- Use
withto avoid forgetting cleanup (e.g.,file.close()), making code safer and cleaner.
File-handling example and a simple custom context manager:
# Using with for file handling
with open("example.txt", "w") as f:
f.write("hello")
# File is closed automatically here
# Custom context manager
class Timer:
import time
def __enter__(self):
self.start = self.time.time()
return self
def __exit__(self, exc_type, exc, tb):
self.end = self.time.time()
print(f"Elapsed: {self.end - self.start:.4f}s")
with Timer():
total = sum(range(1000000)) # do some work Example output (timing will vary):
# Output (example):
Elapsed: 0.0357s 25. Explain Python's import system.
Python's import system locates and loads modules so you can reuse code. When you write import module, Python follows a defined process: it searches for the module in a set of locations (the module search path), loads and executes the module file once, and caches the loaded module in sys.modules so subsequent imports are fast and consistent.
- Search order:
sys.modulescache → built-in modules → file system locations listed insys.path(including the current directory and site-packages). - Import forms:
import module,from module import name, andimport package.module as alias- each has different namespace effects. - Packages are directories with a
__init__.py(modern Python can have namespace packages without__init__.py, but the__init__file is often used for package initialization). sys.modulesprevents repeated execution of a module; modifying the module object insys.modulesaffects later imports.
Small example demonstrating import behavior and sys.modules caching:
# Create a module file named mymod.py with:
# print("mymod loaded")
# value = 42
# Then run this script:
import importlib, sys
import mymod # prints "mymod loaded"
import mymod # no print, loaded from sys.modules
importlib.reload(mymod) # forces re-execution and prints again
print("mymod.value =", mymod.value) Expected terminal sequence:
# Output:
mymod loaded
mymod loaded
mymod.value = 42 Interview tips for imports:
- Know how
sys.pathis constructed and why relative imports can behave differently in packages vs scripts. - Explain how circular imports occur and strategies to avoid them (defer imports, refactor, or use local imports inside functions).
- Mention
importlibfor dynamic imports and__all__to controlfrom module import *behavior.
Closing notes: These five topics often come up in interviews because they reveal both conceptual understanding and practical habits. Practice writing small programs that demonstrate each idea, and when answering in interviews, use short analogies (like "names point to objects" or "duck typing: if it quacks...") to make your explanation friendly and memorable.
Check your understanding
3 questions · no sign-up · misses join your review queue, on this device only
Progress is stored in this browser only - no sign-up, nothing sent anywhere.