Python Core Concepts - Part 2 (Questions 27-52)
Continue your Python mastery with advanced topics including closures, file handling, logging, threading, async programming, and more essential concepts for interviews.
🔐 Closures & Advanced Functions
- 27. Explain closures in Python A closure is a nested function that remembers variables from its enclosing scope, even after the outer function has finished executing.
def outer(x): def inner(y): return x + y return inner add_5 = outer(5) print(add_5(3)) # Output: 8 - 28. Explain context managers They manage resources using
__enter__and__exit__methods.with open('file.txt') as f: print(f.read()) # File is automatically closed after the block
📁 File Handling
- 29. What are Python's file modes? 'r' - Read'w' - Write'a' - Append'rb'/'wb' - Binary'r+' - Read/Write
- 30. How is logging different from print()? print(): Temporary, console-only output for debugging during developmentlogging: Structured, persistent, configurable system with levels (DEBUG, INFO, WARNING, ERROR, CRITICAL)
import logging logging.basicConfig(filename='app.log', level=logging.INFO) logging.info("App started") # Logged in file print("App started") # Only printed to console - 31. How does logging work in Python? The
loggingmodule provides a flexible framework for emitting log messages, supporting different severities and handlers (file, console, network).
⚡ Threading & Multiprocessing
- 32. Differentiate between threading and multiprocessing Threading: Multiple threads within a single process, sharing memory, but limited by the GIL for CPU-bound tasks. Good for I/O-bound operations.Multiprocessing: Multiple processes, each with its own interpreter and memory space, bypassing the GIL for true parallelism. Good for CPU-bound operations.
- 33. When would you use asyncio? Used for concurrent, non-blocking I/O with
asyncandawait, ideal for I/O-bound and high-level structured network code where tasks are cooperative.import asyncio async def fetch_data(): print("Start fetching") await asyncio.sleep(2) # Non-blocking print("Done fetching") asyncio.run(fetch_data())
📦 Packages & Modules
- 34. What are Python packages and modules? Module: A file with Python code (.py file)Package: A collection of modules with
__init__.pyfile - 35. How to manage environments? Use
venvorvirtualenvfor isolated dependencies.# Create python3 -m venv env # Activate (Linux/Mac) source env/bin/activate # Activate (Windows) env\Scripts\activate # Deactivate deactivate
- 36. What is PEP8? Python's official style guide for clean, readable code including indentation, naming conventions, and line length recommendations.
- 37. How do you perform asynchronous file I/O in Python? While Python's built-in
open()is blocking, libraries likeaiofilesor using thread pools (e.g., ThreadPoolExecutor) with asyncio can achieve asynchronous file I/O.
🔤 Type Hints & Data Serialization
- 38. What are type hints? Type hints provide expected data types of variables, function parameters, and return values, improving code readability and enabling static type checking.
def add(x: int, y: int) -> int: return x + y name: str = "John" age: int = 25 - 39. How to handle JSON in Python? Use the
jsonmodule withjson.load()andjson.dump().import json # Load JSON from file with open('data.json') as f: data = json.load(f) # Dump JSON to file with open('output.json', 'w') as f: json.dump({'name': 'John'}, f) - 40. What is pickling and unpickling in Python? Pickling: Serializing Python objects into a byte stream (for saving to file or transferring)Unpickling: Deserializing — converting the byte stream back into an object⚠ Caution: Never unpickle untrusted data — it can execute arbitrary code.
import pickle data = {'a': 1, 'b': 2} # Pickle (serialize) pickle.dump(data, open('f.pkl', 'wb')) # Unpickle (deserialize) obj = pickle.load(open('f.pkl', 'rb'))
🌐 API Calls
- 41. How to make API calls in Python? Use the
requestslibrary for simple API calls.import requests response = requests.get('https://api.github.com') data = response.json() print(response.status_code) - 42. Give an example of an async API call in Python
import asyncio import httpx # A modern, async-friendly HTTP client async def fetch_data(url): async with httpx.AsyncClient() as client: response = await client.get(url) return response.json() async def main(): data = await fetch_data("https://api.example.com/data") print(data) if __name__ == "__main__": asyncio.run(main())
💾 Copy & Memory Operations
- 43. What is the difference between shallow and deep copy? Shallow copy (
copy.copy()): Only copies the top-level object — nested objects are still referencedDeep copy (copy.deepcopy()): Creates a completely independent clone — does not keep any reference to the original's nested objectsimport copy original = [[1, 2], [3, 4]] shallow = copy.copy(original) deep = copy.deepcopy(original) original[0][0] = 'X' print(shallow) # [['X', 2], [3, 4]] - affected print(deep) # [[1, 2], [3, 4]] - not affected
- 44. How do you handle large files efficiently? Use generators or process line by line to avoid loading entire file into memory.
with open('large_file.txt') as f: for line in f: # Process one line at a time process(line) - 45. How do you manage packages and modules in Python? Packages are directories containing modules. Modules are single Python files.
pipis used to install, upgrade, and remove packages from PyPI.
🔧 Advanced Concepts
- 46. What is a generator expression? Similar to list comprehensions but uses parentheses
()instead of square brackets, creating an iterator that yields items one by one, consuming less memory.# List comprehension - creates full list squares_list = [x**2 for x in range(10000)] # Generator expression - yields one at a time squares_gen = (x**2 for x in range(10000))
- 47. Explain the
withstatement in PythonThewithstatement simplifies resource management (like file I/O or locking) by ensuring that a resource is properly acquired before a block of code is executed and released afterwards, even if errors occur. - 49. What is monkey patching in Python? Monkey patching is modifying or extending a class or module at runtime without changing its original source code. Use case: quick fixes or mocking functions during testing.
class Test: def greet(self): print("Hello") def new_greet(): print("Hi, patched!") Test.greet = new_greet # Monkey patching obj = Test() obj.greet() # Output: Hi, patched!⚠ Avoid in production — it can cause unpredictable behavior. - 50. What is duck typing in Python? Duck typing means an object's suitability is determined by behavior (methods/attributes) rather than its actual type. "If it quacks like a duck, it's a duck."
class Duck: def quack(self): print("Quack!") class Person: def quack(self): print("I'm quacking like a duck!") def make_it_quack(obj): obj.quack() # Works with any object that has quack() make_it_quack(Duck()) make_it_quack(Person()) # Both work! - 51. What is method overriding? When a child class defines a method with the same name as a parent class method to modify behavior.
class Parent: def show(self): print("Parent") class Child(Parent): def show(self): print("Child") Child().show() # Output: Child - 52. What is method overloading? Python doesn't support true overloading (like Java); the latest method definition overrides previous ones. However, you can mimic it with default arguments.
class Math: def add(self, a, b=0, c=0): return a + b + c m = Math() print(m.add(2)) # 2 print(m.add(2, 3)) # 5 print(m.add(2, 3, 4)) # 9