programming beginner 10 sample questions

Python MCQ Practice Test

Basics of syntax and semicolons vs. colons. Understanding list comprehensions and generators. Key libraries like random, math, and datetime.

Q1. Consider a Python program utilizing multiprocessing with shared memory through a `multiprocessing.Array` object. The program creates three processes, each incrementing a shared integer counter 1000 times. However, the final counter value consistently falls short of the expected 3000. Which of the following is the MOST likely explanation for this discrepancy, assuming no race conditions are explicitly handled?

Explanation: Each process performs a non-atomic read-modify-write on the shared counter. If the scheduler preempts a process after it reads the old value but before it writes, another process's increment is overwritten, so the total falls short of 3000. The GIL serializes threads within one process but does nothing across separate processes, and multiprocessing.Array supports ordinary integer writes - the race is in the read-modify-write sequence, not memory alignment or write atomicity.

Q2. Consider a Python program utilizing multiprocessing with a shared list accessed by multiple processes. Each process appends a unique integer to this list. Without employing any explicit locking mechanisms (like `Lock` or `RLock`), which statement BEST describes the potential outcome regarding the final state of the shared list?

Explanation: Without proper locking, multiple processes writing to the shared list concurrently lead to race conditions. Appends are not atomic; the internal operations of appending (getting the length, allocating new memory, copying elements) can be interrupted by other processes. This can cause integers to be partially written or completely missed, leading to an unpredictable order and potential duplicates. A `RuntimeError` isn't guaranteed, but the data corruption is almost certain. Only in very specific, unlikely scenarios involving CPU scheduling might the order be preserved without any errors. The core issue is the lack of atomicity in list append operations within a multiprocessing environment.

Q3. Consider a Python program utilizing multiprocessing.Pool. You submit a task that raises an exception within a worker process. Which statement BEST describes the behavior of the Pool's `map` or `apply_async` methods in handling this exception?

Explanation: Python's multiprocessing Pool doesn't inherently handle exceptions raised within worker processes; these exceptions are raised in the main process when the results are retrieved, causing the main process to crash unless a mechanism (e.g., try-except blocks) is used to gracefully handle them. Options A and D are incorrect as they misrepresent the behavior; the Pool itself does not retry or cause immediate termination. Option B is incorrect, because the exception will not be silently ignored, instead, it will be raised.

Q4. Consider a Python program utilizing multiprocessing's Pool.map() with a function that modifies a shared list within its execution. Which statement BEST describes the potential outcome and the necessary precaution to avoid data corruption?

Explanation: Multiprocessing in Python bypasses the GIL, allowing true parallelism. However, this means that multiple processes can attempt to modify the shared list concurrently, leading to race conditions and unpredictable results. Using synchronization primitives such as locks (threading.Lock) or multiprocessing-safe queues ensures that access to the shared list is properly controlled, preventing data corruption.

Q5. Consider a Python program utilizing multiprocessing with shared memory via a `multiprocessing.Array`. The program involves multiple processes concurrently writing to the array. Which statement BEST describes the necessary synchronization mechanism to guarantee data integrity and avoid race conditions, assuming the array stores integers?

Explanation: While atomic operations (option C) might seem appealing, they are not always sufficient for complex write operations on integers. A `threading.Lock` (option A) is inappropriate for multiprocessing because it's designed for threads within a single process. The GIL (option D) is irrelevant; multiprocessing bypasses the GIL. A `multiprocessing.Lock` (option B) provides the necessary process-level synchronization to ensure that only one process accesses and modifies the shared array at any given time, preventing race conditions and guaranteeing data integrity.

Q6. Consider a Python program using multiprocessing.Pool. The program applies a CPU-bound function to a large iterable. Which of the following strategies would MOST effectively mitigate the Global Interpreter Lock (GIL) limitations and maximize performance in this scenario?

Explanation: While increasing the number of processes can help, exceeding the number of CPU cores leads to diminishing returns and context-switching overhead. `multiprocessing.dummy` uses threads and is thus still subject to the GIL. `asyncio` is beneficial for I/O-bound operations, not CPU-bound ones. The most effective solution for CPU-bound tasks within multiprocessing is to minimize the internal use of locks and other synchronization primitives within the function being executed, allowing each process to operate more independently and thus bypass the GIL's limitations on true parallelism.

Q7. Consider a Python program utilizing asynchronous I/O with asyncio. You have a function `fetch_data(url)` that uses `aiohttp` to fetch data from a URL and returns the data as a string. You need to concurrently fetch data from multiple URLs and then process each result. Which approach will MOST efficiently handle potential exceptions during the concurrent fetches while ensuring all URLs are attempted, collecting both successful results and error details?

Explanation: While `asyncio.gather` is suitable for concurrent operations, simply using `try...except` blocks within or outside the gather doesn't efficiently handle exceptions arising from different URLs simultaneously. Using `asyncio.shield` prevents an exception in one coroutine from stopping the others. A custom coroutine allows for granular control over error handling and result collection, efficiently providing a comprehensive status of all URLs processed.

Q8. Consider a Python program utilizing multiprocessing.Pool. You submit a task that raises an exception within a worker process. Which statement BEST describes the behavior of the Pool's `apply_async` method when encountering this exception?

Explanation: The `apply_async` method in Python's `multiprocessing.Pool` doesn't halt the entire process upon encountering an exception within a worker. Instead, it typically catches the exception, logs it (depending on your configuration), and returns a result that indicates failure, allowing the pool to continue processing other tasks. Immediate process termination or silent ignoring are not standard behavior.

Q9. Consider a Python program utilizing multiprocessing with a shared list managed via a `multiprocessing.Manager`. Which statement BEST describes the potential performance implications of using `list.append()` within multiple processes concurrently accessing this shared list, compared to using a `multiprocessing.Queue` for inter-process communication?

Explanation: While the `multiprocessing.Manager` provides a way to share data between processes, directly using `list.append()` on a shared list in multiple processes concurrently is highly susceptible to race conditions and can lead to unpredictable behavior and data corruption. `multiprocessing.Queue` uses locks and internal synchronization mechanisms designed for efficient and safe inter-process communication, avoiding the pitfalls of directly manipulating shared mutable objects. Therefore, using a `Queue` for this task results in both correct and more performant code.

Q10. Consider a Python program using multiprocessing. The program creates a shared array using `multiprocessing.Array('i', 10)` and multiple processes access and modify this array concurrently without any explicit locking mechanisms. Which statement BEST describes the potential outcome, given that processes modify the array in non-atomic operations?

Explanation: Without proper locking mechanisms (like using a `multiprocessing.Lock` or similar synchronization primitives), concurrent access to a shared array in Python's multiprocessing can lead to race conditions. Non-atomic operations mean that a process's modification might be interrupted by another process, resulting in data corruption and unpredictable behavior. The program might not always crash, but it won't guarantee correct results.

That was just a sample. Sign up to unlock the full question bank with timed tests and certificates.

Sign Up Free
Python MCQ Practice Test | Mind Hustle