Python Essentials: Decorators, Generators, and Concurrency Quiz Quiz

Sharpen your backend development skills with this quiz focused on Python decorators, generators, and concurrency. Assess your understanding of core Python interview concepts in a practical, scenario-based format tailored for programmers seeking robust, efficient code.

  1. Identifying Decorators

    Which symbol is used in Python to apply a decorator to a function?

    1. @
    2. #
    3. &
    4. %

    Explanation: The @ symbol is placed directly above a function definition to apply a decorator in Python, signaling that the function is being modified or extended. The # symbol is for comments and does not affect function behavior. The & and % symbols are not used for decorators in Python and would result in syntax errors in this context.

  2. Generator Output

    What does a Python generator function return when called?

    1. A generator object
    2. A list
    3. A tuple
    4. An integer

    Explanation: Calling a generator function returns a generator object, which can be iterated to yield values one at a time. It does not return a list or tuple, as those require all values to be precomputed and stored. An integer is unrelated to the output of a generator function.

  3. Multiple Decorators Application

    How are multiple decorators applied to a single Python function?

    1. By stacking multiple @decorator lines above the function
    2. By listing them on a single line separated by commas
    3. By enclosing them in square brackets
    4. By chaining them after the function keyword

    Explanation: Multiple decorators are applied by stacking several @decorator lines above the function definition, each on a separate line. Comma-separating on one line, using square brackets, or chaining after the 'def' keyword are invalid Python syntax for decorators.

  4. Generator Expression Syntax

    Which syntax correctly creates a generator expression that yields squares of numbers from 0 to 4?

    1. (x * x for x in range(5))
    2. [x * x for x in range(5)]
    3. list(x * x for x in range(5))
    4. {x * x for x in range(5)}

    Explanation: Generator expressions use parentheses, like (x * x for x in range(5)), to lazily compute values. Square brackets create list comprehensions, not generators. Wrapping the expression in 'list()' evaluates and consumes the generator, while curly braces form a set comprehension.

  5. Threading Purpose

    What is the primary purpose of using the threading module in Python?

    1. To execute code concurrently within a single process
    2. To execute scripts in different programming languages
    3. To automatically optimize slow code
    4. To create new data types

    Explanation: The threading module allows multiple threads to run concurrently within the same process, improving responsiveness in certain situations. It does not launch code in other languages, cannot optimize code performance on its own, and is not intended for creating data types.

  6. Decorator Argument Passing

    When you decorate a function that accepts arguments, what must the decorator's wrapper function also accept?

    1. *args and **kwargs
    2. Only a single argument
    3. No arguments
    4. A specific keyword argument

    Explanation: To ensure the decorator can handle any combination of positional and keyword arguments, the wrapper function inside the decorator should accept *args and **kwargs. Accepting only a single argument, none, or requiring a specific keyword is limiting and breaks compatibility.

  7. next() on Generators

    What does the built-in function next() do when used on a generator object?

    1. Retrieves the next value yielded by the generator
    2. Returns the total length of the generator
    3. Terminates the generator immediately
    4. Resets the generator to the beginning

    Explanation: The next() function retrieves the next value produced by the generator or raises StopIteration if exhausted. It does not measure the generator's length, terminate it, or reset its state. Generators cannot be reset directly.

  8. Decorator Stack Order

    If a function is decorated with @dec1 above @dec2, which decorator is applied first?

    1. dec2 is applied first, then dec1
    2. dec1 is applied first, then dec2
    3. Both are applied simultaneously
    4. Only dec1 is applied

    Explanation: Decorators are applied from the innermost (closest to the function) outward, so @dec2 is wrapped first, then @dec1 wraps that result. Both apply, but not at the same moment nor only the top-most. The order is significant in how they transform the function.

  9. yield vs. return

    What is the primary difference between using 'yield' and 'return' in a Python function?

    1. 'yield' produces values lazily, 'return' exits the function with a value
    2. 'yield' ends the function, 'return' keeps it running
    3. 'yield' stores results in a list, 'return' gives a tuple
    4. 'yield' is used only in decorators, 'return' is not

    Explanation: 'yield' allows functions to produce values one at a time, suspending their state between calls, while 'return' immediately terminates the function and returns a single value. 'yield' does not collect results in a list, nor is it exclusive to decorators.

  10. Concurrency Module Choice

    Which Python module is commonly used for concurrent execution using processes rather than threads?

    1. multiprocessing
    2. threading
    3. asyncore
    4. collections

    Explanation: The multiprocessing module provides support for concurrent execution using multiple processes, bypassing some limitations of threading in Python. The threading module is specific to threads, asyncore is used for asynchronous socket handling, and collections is unrelated to concurrency.

  11. Statefulness of Generators

    Are generator functions in Python stateful across multiple calls to next()?

    1. Yes, they retain local variables between yields
    2. No, they restart from the top each time
    3. Only if declared as global
    4. Only if decorated

    Explanation: Generators automatically save their state, including local variables and the position after last yield, between calls to next(). They do not restart from the top or require variables to be global or decorated to retain state, as this is the built-in behavior of generator functions.

  12. Decorator Function Basics

    Which of the following best describes a Python decorator?

    1. A function that takes another function and returns a modified function
    2. A built-in Python data type
    3. A special type of class used for inheritance
    4. A keyword for handling errors

    Explanation: Decorators are higher-order functions that accept a function and return a new or wrapped version of it. They are not data types, classes, or error-handling keywords. Their main purpose is to add or modify behavior of existing functions.

  13. Concurrent Futures Purpose

    What is the main use of the concurrent.futures module in Python?

    1. To simplify running tasks in threads or processes
    2. To generate random numbers
    3. To validate future dates
    4. To compile Python code

    Explanation: concurrent.futures provides high-level interfaces for executing code asynchronously in separate threads or processes through pools. Its purpose is not number generation, date validation, or code compilation, making it focused on concurrent execution.

  14. Generator Exhaustion

    What exception is raised when a generator is exhausted and next() is called again?

    1. StopIteration
    2. ValueError
    3. TypeError
    4. KeyError

    Explanation: When a generator runs out of values, calling next() leads to a StopIteration exception. ValueError, TypeError, and KeyError are not related to generator exhaustion, as they serve different errors in Python.

  15. Functionality Extension

    If you want to record the execution time of a function without altering its code, what Python technique is commonly used?

    1. Using a decorator
    2. Rewriting the function
    3. Using a generator
    4. Creating a context manager

    Explanation: Decorators allow additional behavior, like timing, to be added without modifying the core function code. Rewriting the function is more intrusive, a generator does not provide timing, and while a context manager could time blocks, it's not the standard approach for timing functions.

  16. Limitation of Threading

    Which of the following limitations applies to Python's standard threading for CPU-bound tasks?

    1. The Global Interpreter Lock (GIL) limits true parallel execution of threads
    2. Threads cannot perform file I/O
    3. Threads are faster for all types of work
    4. Threads require explicit memory management

    Explanation: Python's GIL prevents multiple native threads from executing Python bytecode simultaneously in one process, limiting efficiency for CPU-bound work. Threads can perform file I/O, are not always the fastest, and Python's memory management is automatic, not manual.