Courseiva

Certified Associate Python Programmer PCAP (PCAP) — Questions 76150

169 questions total · 3pages · All types, answers revealed

Page 1

Page 2 of 3

Page 3
76
MCQmedium

Your company has two separate Python packages: 'app' and 'lib'. They are maintained by different teams. 'app' depends on 'lib', but 'lib' is still under development and its API changes frequently. To avoid breaking 'app', the team decides to use a virtual environment and install a specific version of 'lib'. However, during development, they need to test 'app' with the latest 'lib' changes from the Git repository. The current workflow is: (1) activate virtual env, (2) install 'lib' from local source using `pip install -e /path/to/lib`. This installs 'lib' as a development package. But one developer reports that after pulling latest 'lib' changes, importing 'lib' in 'app' still uses the old version even after re-running pip install -e. What is the most likely reason?

A.Python caches imported modules in sys.modules, so importing again does not reload the module from disk.
B.The package 'lib' is being imported as a namespace package, so changes are not picked up.
C.The .pyc files are not being invalidated because the timestamps are not updated.
D.The editable install may still point to an old copy of the library if the source directory was moved or if there is a stray .egg-link file.
AnswerD

An editable install for 'lib' registers the source directory via a .pth file or an .egg-link file, which adds that directory to sys.path. If the source directory was moved after the editable install, the recorded path becomes stale; alternatively, a leftover .egg-link from an earlier install can point to the old location. Re-running pip install -e should update this, but if it happened before the move or was interrupted, the import mechanism will still reference the old copy, so changes in the current directory are ignored.

Why this answer

The most likely reason is D. When using `pip install -e` (editable install), pip creates a special `.egg-link` file (or similar pointer) in the site-packages directory that points to the source directory. If the source directory was moved, renamed, or if a stale `.egg-link` file remains from a previous install, pip may still reference the old location, causing the old version to be imported even after re-running the install command.

This is a known subtlety of editable installs, especially when the source code is managed under version control and the directory structure changes.

Exam trap

Python Institute often tests the subtle difference between a stale import cache (sys.modules) and a stale install pointer (editable install link), leading candidates to incorrectly choose the caching option when the real issue is a broken or outdated path reference in the development install.

How to eliminate wrong answers

Option A is wrong because Python's `sys.modules` cache only affects modules already imported in the current interpreter session; re-running `pip install -e` and then starting a fresh Python process would not be affected by this cache. Option B is wrong because namespace packages are a different concept (PEP 420) and do not relate to the failure to pick up changes after an editable install; the issue is about the install pointer, not the package type. Option C is wrong because `.pyc` file invalidation is based on source file timestamps or hash comparison, and `pip install -e` does not modify `.pyc` files; the problem is that the import system is loading from a different location entirely, not that bytecode is stale.

77
MCQhard

Which of the following correctly uses an abstract base class to enforce that all subclasses implement a 'make_sound' method? (Assume ABC imported)

A.from abc import ABC, abstractmethod\nclass Animal(ABC):\n @abstractmethod\n def make_sound(self):\n pass
B.from abc import abstractmethod\nclass Animal:\n @abstractmethod\n def make_sound(self):\n pass
C.class Animal:\n def make_sound(self):\n return None
D.class Animal:\n def make_sound(self):\n raise NotImplementedError
AnswerA

Proper ABC with abstractmethod.

Why this answer

It imports both `ABC` and `abstractmethod` from the `abc` module, defines `Animal` as a subclass of `ABC`, and decorates `make_sound` with `@abstractmethod`. This combination prevents instantiation of `Animal` and forces any concrete subclass to override `make_sound`, or else a `TypeError` is raised at instantiation time.

Exam trap

Python Institute often tests whether candidates know that `@abstractmethod` alone does not make a class abstract — the class must explicitly inherit from `ABC` (or have its metaclass set to `ABCMeta`), otherwise the decorator is ignored and instantiation is allowed.

How to eliminate wrong answers

Option B is wrong because it does not make `Animal` a subclass of `ABC`; without inheriting from `ABC`, the `@abstractmethod` decorator has no effect and the class can be instantiated directly, so no enforcement occurs. Option C is wrong because it defines a concrete method that simply returns `None`; subclasses are free to ignore it, and there is no abstract mechanism to require overriding. Option D is wrong because raising `NotImplementedError` is a runtime convention, not a compile-time or instantiation-time enforcement; a subclass that forgets to override `make_sound` will only fail when the method is called, not when the object is created, and the base class is not abstract.

78
MCQmedium

Which method returns the lowest index where a specified substring is found, or -1 if not found?

A.find()
B.locate()
C.search()
D.index()
AnswerA

find returns the lowest index or -1 if not found.

Why this answer

The `find()` method in Python returns the lowest index where the specified substring is found within the string, or -1 if the substring is not present. This behavior directly matches the question's requirement, making option A correct.

Exam trap

The PCAP exam often tests the distinction between `find()` and `index()`, where candidates mistakenly choose `index()` because it returns an index, forgetting that it raises an exception on failure instead of returning -1.

How to eliminate wrong answers

Option B is wrong because `locate()` is not a built-in string method in Python; it exists in other languages like JavaScript but not in Python's standard library. Option C is wrong because `search()` is a method from the `re` module for regex pattern matching, not a string method, and it returns a match object or None, not an index or -1. Option D is wrong because `index()` raises a `ValueError` exception when the substring is not found, rather than returning -1.

79
Multi-Selecteasy

Which TWO of the following are special methods in Python?

Select 2 answers
A.`__bar__`
B.`__main__`
C.`__init__`
D.`__str__`
E.`__foo__`
AnswersC, D

This is the instance initializer method.

Why this answer

`__init__` is a predefined special method in Python used as a constructor to initialize an object's state when an instance of a class is created. It is automatically invoked by the Python runtime upon object instantiation, making it a core part of the object-oriented programming model in Python.

Exam trap

Python Institute often tests the distinction between actual special methods (like `__init__` and `__str__`) and arbitrary dunder-named attributes that are not part of Python's language specification, leading candidates to mistakenly think any name with double underscores is a special method.

80
MCQhard

Refer to the exhibit. What is the effect of using 'from None' in the raise statement?

A.It re-raises the original ValueError
B.It causes a syntax error
C.It suppresses the exception chain and only shows the TypeError
D.It chains the TypeError to the original ValueError
AnswerC

Using `from None` in a `raise` statement sets the `__suppress_context__` attribute of the exception to `True`. When the TypeError propagates, Python's default exception handler checks this flag and, because it is true, omits the implicit display of the original ValueError and its traceback. The final output therefore contains only the TypeError, either in the interactive shell or in a captured traceback.

Why this answer

Using 'from None' suppresses the chaining of exceptions, so the original ValueError is not shown in the traceback.

81
MCQmedium

Refer to the exhibit. A script executes 'from mypackage import *'. Which functions are available in the global namespace?

A.Only func from module_a
B.It raises an ImportError because __all__ should contain function names
C.None, because __all__ lists modules, not functions
D.func from both module_a and module_b
AnswerC

Correct. __all__ defines what names are imported; here it imports the modules, so functions remain in the module namespace.

Why this answer

When `from mypackage import *` is executed, Python looks for the `__all__` list in the package's `__init__.py` file. In this exhibit, `__all__` is defined as `['module_a', 'module_b']`, which are module names, not function names. The `import *` statement imports the modules listed in `__all__` into the global namespace, not their individual functions.

Therefore, `func` from either module is not directly available; you would need to reference them as `module_a.func` or `module_b.func`.

Exam trap

The trap here is that candidates often assume `__all__` must contain function or variable names, but it can also list submodule names, and `import *` only imports those listed names—not their nested contents—into the global namespace.

How to eliminate wrong answers

Option A is wrong because `func` from `module_a` is not directly imported into the global namespace; only the module `module_a` itself is imported. Option B is wrong because `__all__` can contain module names or attribute names; it does not raise an `ImportError` when it contains module names—it simply imports those modules. Option D is wrong because `func` from both modules is not directly available; only the modules `module_a` and `module_b` are imported into the global namespace.

82
MCQmedium

Given: class A: def method(self): print('A'); class B(A): def method(self): super().method(); print('B'); class C(A): def method(self): super().method(); print('C'); class D(B, C): pass. What is printed by D().method()?

A.A B C
B.A C B
C.C A B
D.B A C
AnswerB

Correct call order via MRO.

Why this answer

Python's MRO (Method Resolution Order) for class D, which inherits from B and C (both inheriting from A), follows the C3 linearization algorithm. The MRO for D is D -> B -> C -> A, so calling D().method() triggers B.method(), which calls super().method() (resolving to C.method()), which calls super().method() (resolving to A.method()), printing 'A', then back to C prints 'C', then back to B prints 'B', resulting in 'A C B'.

Exam trap

Python Institute often tests the misconception that super() always calls the immediate parent class (A) in a linear chain, rather than following the full MRO, leading candidates to pick 'A B C' instead of the correct 'A C B'.

How to eliminate wrong answers

Option A is wrong because it assumes a simple left-to-right depth-first order without considering that super() in B resolves to C (the next class in MRO), not directly to A, so the output is not 'A B C'. Option C is wrong because it incorrectly suggests C.method() is called first, but the MRO starts with D, then B, not C. Option D is wrong because it implies B.method() prints 'B' before its super() chain completes, but the actual order is A (from A.method), then C (from C.method), then B (from B.method).

83
MCQeasy

A developer needs to check if a string contains only alphanumeric characters. Which string method should be used?

A.s.isnumeric()
B.s.isalnum()
C.s.isdigit()
D.s.isalpha()
AnswerB

s.isalnum() exactly implements the required test: it returns True only for non-empty strings where every character is a Unicode letter or digit, accepting both 'hello123' and accented letters like 'café'. It also recognizes Unicode digits such as '١' while correctly rejecting spaces, punctuation, and symbol characters like '#' or '!'. Because the condition is precisely that the string contains only alphanumeric characters, this is the correct method and also implies that isalpha() or isdigit() would be too restrictive individually.

Why this answer

The `isalnum()` method returns `True` if all characters in the string are alphanumeric (letters or digits) and the string is non-empty. This directly matches the requirement to check for only alphanumeric characters, covering both letters and digits without any other characters.

Exam trap

The trap here is that candidates often confuse `isalnum()` with `isalpha()` or `isdigit()`, mistakenly thinking that checking for letters only or digits only is sufficient, when the question explicitly requires both letters and digits (alphanumeric).

How to eliminate wrong answers

Option A is wrong because `isnumeric()` returns `True` only for numeric characters (including Unicode numeric values like fractions, Roman numerals, etc.), not for letters, so it fails to check for alphanumeric content. Option C is wrong because `isdigit()` returns `True` only for decimal digit characters (0-9 and certain Unicode digits), excluding letters entirely. Option D is wrong because `isalpha()` returns `True` only for alphabetic characters (letters), excluding digits, so it would reject strings containing numbers.

84
MCQhard

A developer is tasked with validating user input that must be a 10-digit phone number. The input may contain spaces, dashes, and parentheses. Which approach best ensures the input contains exactly 10 digits?

A.if len([c for c in s if c.isdigit()]) == 10:
B.if len(s) >= 10 and s.isdigit():
C.if s[:10].isdigit():
D.if s.isdigit() and len(s) == 10:
AnswerA

This expression builds a list containing only the digit characters from the input and then compares its length to 10. It therefore passes any string that contains exactly ten digits, regardless of additional letters, spaces, hyphens, or punctuation, because non-digits are simply filtered out before counting. This precisely matches the requirement to validate that user input contains ten digits without insisting on a specific format.

Why this answer

Uses a list comprehension to filter only digit characters from the input string `s` and then checks if the count of those digits is exactly 10. This correctly handles any non-digit characters (spaces, dashes, parentheses) by ignoring them, ensuring the validation focuses solely on the presence of exactly ten digits.

Exam trap

Python Institute often tests the distinction between checking if a string *contains* a certain number of digits versus checking if the string *itself* is entirely composed of digits, leading candidates to mistakenly choose options that require the entire string to be numeric.

How to eliminate wrong answers

Option B is wrong because `s.isdigit()` returns `True` only if *all* characters in the string are digits, so it would reject valid inputs containing spaces, dashes, or parentheses. Option C is wrong because `s[:10].isdigit()` only checks the first ten characters, ignoring any non-digit characters that might appear later, and also fails to verify that the entire string contains exactly ten digits (e.g., a 15-digit string with first ten digits would incorrectly pass). Option D is wrong because `s.isdigit()` again requires the entire string to consist solely of digits, which would reject any input with formatting characters, even if it contains exactly ten digits.

85
MCQhard

A developer is creating a custom exception hierarchy for a library. The base exception is `LibraryError`. Which definition ensures that subclasses can be caught using the parent exception, but also allows distinguishing between different error types?

A.class LibraryError: pass class FileError(LibraryError): pass class ParseError(LibraryError): pass
B.class LibraryError(BaseException): pass class FileError(LibraryError): pass class ParseError(LibraryError): pass
C.class LibraryError(Exception): pass class FileError(LibraryError): pass class ParseError(LibraryError): pass
D.class LibraryError(Exception): pass class FileError(Exception): pass class ParseError(Exception): pass
AnswerC

This is the canonical pattern: the library base class derives from Exception, so all library errors are ordinary, catchable exceptions; the specific subclasses then derive from that base class. Code catching LibraryError will also catch FileError and ParseError, while code can still catch either refined type independently. This gives a consistent API and lets the library evolve by adding new specific errors without breaking callers that rely on the base type.

Why this answer

It defines `LibraryError` as a subclass of `Exception`, which is the proper base class for all user-defined exceptions in Python. Subclasses `FileError` and `ParseError` inherit from `LibraryError`, so they can be caught with `except LibraryError` while still being distinguishable by their own type. This follows the standard Python exception hierarchy, where custom exceptions should derive from `Exception`, not `BaseException` or no base class.

Exam trap

Python Institute often tests the distinction between `Exception` and `BaseException`, and the trap here is that candidates mistakenly think any class named 'Error' is automatically an exception, or they choose Option B thinking `BaseException` is the correct base for all custom exceptions.

How to eliminate wrong answers

Option A is wrong because `LibraryError` does not inherit from `Exception`; it is a plain class, so it cannot be caught by a standard `except Exception` clause and does not integrate with Python's exception handling mechanism. Option B is wrong because `LibraryError` inherits from `BaseException`, which is reserved for system-exiting exceptions like `SystemExit` and `KeyboardInterrupt`; catching `BaseException` is discouraged as it can suppress critical signals. Option D is wrong because `FileError` and `ParseError` both inherit directly from `Exception` rather than from `LibraryError`, so they cannot be caught collectively as `LibraryError` and break the intended hierarchy.

86
MCQmedium

You are a data analyst working with a dataset of customer reviews. Each review is stored as a string in a list. You need to count how many reviews contain the word 'excellent' (case-insensitive). However, the word might appear as 'Excellent', 'EXCELLENT', or even with punctuation like 'excellent!'. The current code uses 'excellent' in review.lower(), but this fails if 'excellent' is part of another word like 'unexcellent'. You need to ensure that only the whole word 'excellent' is counted. Which code modification will correctly count whole word occurrences?

A.Use re.search(r'\bexcellent\b', review, re.IGNORECASE)
B.Use 'excellent' in review.lower().split()
C.Use review.lower().count('excellent') > 0
D.Use review.lower().find('excellent') != -1
AnswerA

The \b word boundary anchors ensure that 'excellent' is matched only when it stands as its own word, not as a substring of a larger token, while the re.IGNORECASE flag makes the match case-insensitive. Because re.search scans the entire string but the boundary restricts the match position, this option correctly finds 'Excellent', 'excellent.', and 'excellent' while rejecting 'unexcellent'. This is the only approach that combines whole-word semantics with case-insensitive matching in a single call.

Why this answer

`re.search(r'\bexcellent\b', review, re.IGNORECASE)` uses the `\b` word boundary anchor to ensure that 'excellent' is matched as a whole word, not as part of another word like 'unexcellent'. The `re.IGNORECASE` flag handles case-insensitive matching, covering 'Excellent', 'EXCELLENT', etc. This approach also correctly handles punctuation attached to the word, such as 'excellent!', because the word boundary matches between a word character and a non-word character.

Exam trap

Python Institute often tests the distinction between substring matching and whole-word matching, and the trap here is that candidates assume `in` with `split()` or `count()` handles whole words, but they fail to account for punctuation or compound words, leading to incorrect counts.

How to eliminate wrong answers

Option B is wrong because `'excellent' in review.lower().split()` splits the string on whitespace only, so it would fail if 'excellent' is followed by punctuation like 'excellent!' (the split would keep the exclamation mark attached, making the word 'excellent!' not equal to 'excellent'). Option C is wrong because `review.lower().count('excellent') > 0` counts substring occurrences, so it would match 'excellent' inside 'unexcellent' and count it incorrectly. Option D is wrong because `review.lower().find('excellent') != -1` also performs a substring search, matching 'excellent' as part of a larger word like 'unexcellent'.

87
MCQmedium

A developer is building a logging system that writes logs to a file. The system should handle disk-full situations gracefully without crashing the main application. Which approach is appropriate?

A.Check disk space before each write; if low, skip logging.
B.Wrap the entire application in a try/except that catches all exceptions.
C.Let the OSError propagate to the main program's exception handler.
D.Wrap the log write in a try/except that catches OSError and writes to stderr as fallback.
AnswerD

Wrapping only the write operation in a try/except that specifically catches OSError is the correct pattern: OSError is the parent class of errors like disk full, permission denied, and other I/O failures, so it captures the exact failure mode. Falling back to sys.stderr preserves the log entry and keeps the application running; if stderr itself fails, you can chain another exception or silently drop the record, but the primary failure is isolated. This targeted fallback also avoids hiding non-I/O bugs, unlike a global exception handler.

Why this answer

It uses a targeted try/except block around only the log write operation, catching OSError (which includes disk-full conditions) and falling back to stderr. This prevents the main application from crashing while still reporting the error, adhering to the principle of handling exceptions at the point where they occur and only when you can meaningfully recover.

Exam trap

Python Institute often tests the distinction between catching overly broad exceptions (Option B) versus catching specific exceptions (Option D), and the trap here is that candidates may think 'catching all exceptions' is a safe catch-all, but it actually hides programming errors and violates Python best practices.

How to eliminate wrong answers

Option A is wrong because checking disk space before each write is unreliable (race conditions, non-atomic check-then-act) and adds unnecessary overhead; it also does not handle other OSError scenarios like permission errors. Option B is wrong because wrapping the entire application in a blanket try/except that catches all exceptions (including KeyboardInterrupt, SystemExit) is an anti-pattern that masks bugs, violates the principle of catching specific exceptions, and can leave the application in an inconsistent state. Option C is wrong because letting OSError propagate to the main program's exception handler typically results in an unhandled exception that terminates the application, which is exactly what the developer wants to avoid.

88
MCQeasy

A Python script imports the module 'my_module'. The developer wants to ensure that when the script is run directly, it executes a specific function, but when imported as a module, that function is not executed. Which code snippet achieves this?

A.if __name__ == '__main__': run()
B.if __name__ == '__main__': run()
C.if os.environ.get('RUN_MAIN'): run()
D.if sys.argv[0] == 'my_module': run()
AnswerA, B

This is the canonical Python idiom for conditional execution. The interpreter assigns the special variable __name__ the value '__main__' only when the source file is run directly as the main program (e.g., `python my_module.py`). When the file is imported as a module, __name__ becomes the module's fully qualified name, so the equality check fails and run() is not invoked, allowing safe import without side effects.

Why this answer

Both options A and B are correct because they are identical and represent the standard Python idiom `if __name__ == '__main__': run()`. When the script is run directly, Python sets `__name__` to `'__main__'`, triggering the function. When imported, `__name__` is the module name, so the function is not executed.

Options C and D are incorrect: C relies on an environment variable that is not standard, and D checks `sys.argv[0]` which is the script path, not the module name.

Exam trap

Python Institute often tests the distinction between `__name__` and `sys.argv` or environment variables, trapping candidates who confuse the script's filename with the module's name or who think an external flag is needed to control execution.

How to eliminate wrong answers

Option A is wrong because it is identical to option B and not a distinct code snippet; in the context of the question, both A and B are the same correct answer, but only one can be selected. Option C is wrong because `os.environ.get('RUN_MAIN')` checks for an environment variable that is not automatically set by Python; this would require manual configuration and does not reflect the standard import-time vs. run-time behavior. Option D is wrong because `sys.argv[0]` contains the script name or path used to invoke the interpreter, not the module name; it would never equal `'my_module'` when the script is imported, and it fails to distinguish between direct execution and import.

89
MCQhard

What is the output of the Python code after reading the config.txt file?

A.8080 (as string)
B.An exception is raised.
C.8080
D.'8080'
AnswerC

This is correct because the code reads the configuration value and converts it to an integer using int() (or a ConfigParser getint() call). The integer 8080 is then passed to print(), which displays the number without quotes. Since the conversion succeeds, the output is exactly the integer 8080.

Why this answer

The code reads the config.txt file and splits its content by newlines. The first line contains 'port=8080', and after splitting by '=', the second element is '8080'. The int() function converts this string to the integer 8080, which is then printed.

Option C is correct because the output is the integer 8080, not a string or quoted form.

Exam trap

The trap here is that candidates confuse the internal data type (string vs integer) with the printed output, assuming that because the source is a string, the output must also be a string or quoted, when in fact int() converts it to an integer and print() displays it without quotes.

How to eliminate wrong answers

Option A is wrong because the output is an integer, not a string; int() converts the string '8080' to an integer, so the printed value is 8080 without quotes. Option B is wrong because no exception is raised: the file is opened successfully, split operations are valid, and int('8080') is a valid conversion. Option D is wrong because the output is the integer 8080, not the string '8080' with quotes; print() outputs the integer representation without quotes.

90
MCQmedium

A developer needs to count the number of occurrences of the substring 'is' in the string 'This is a test. Is this a test?'. Which code correctly performs the count?

A.'This is a test. Is this a test?'.split().count('is')
B.'This is a test. Is this a test?'.count('is')
C.'This is a test. Is this a test?'.index('is')
D.'This is a test. Is this a test?'.find('is')
AnswerB

Correctly counts overlapping? No, count does not count overlapping, but 'is' appears at positions 5 and 17, not overlapping, so returns 2.

Why this answer

Python's string method `count(substring)` returns the number of non-overlapping occurrences of the substring in the string. In 'This is a test. Is this a test?', 'is' appears twice (in 'This' and 'is'), and the method counts them correctly, ignoring case sensitivity (the capitalized 'Is' is not counted).

Exam trap

Python Institute often tests the distinction between string methods that return indices (`find`, `index`) versus those that return counts (`count`), and the trap here is that candidates confuse `count()` with `find()` or `index()`, or incorrectly assume `split().count()` works for substring counting.

How to eliminate wrong answers

Option A is wrong because `split()` breaks the string into a list of words (e.g., ['This', 'is', 'a', 'test.', 'Is', 'this', 'a', 'test?']), and then `count('is')` on that list counts only exact list element matches, not substring occurrences — it would return 1 (for the word 'is'), not 2. Option C is wrong because `index('is')` returns the index of the first occurrence of the substring (2) and raises a ValueError if not found, not a count. Option D is wrong because `find('is')` returns the index of the first occurrence (2) or -1 if not found, not a count.

91
MCQhard

Refer to the exhibit. What is the output?

A.'100'
B.100
C.True
D.Error
AnswerB

Official answer: print('100') displays the sequence of characters 1, 0, 0 on the console. The print() function strips the syntactic quotes and outputs the raw string content, so the visible result is 100 without surrounding quotation marks. This is the standard behavior of print() in Python 3.

Why this answer

The code `print('100')` outputs the string `100` without quotes. In Python, `print()` displays the value passed to it; when a string literal is passed, it prints the characters of the string, not the surrounding quotes. Therefore, the output is `100` (the integer-like string, but as a string).

Option B is correct because it shows the numeric value without quotes, which is how Python's `print()` renders a string.

Exam trap

The trap here is that candidates confuse the string literal representation (with quotes) with the printed output, mistakenly thinking that `print('100')` will display the quotes as part of the output.

How to eliminate wrong answers

Option A is wrong because it shows the output with single quotes around `100`, but Python's `print()` function does not include quotes in the output; quotes are only used in the source code to denote a string literal. Option C is wrong because `'100'` is a string, not a boolean; printing it does not produce `True` or `False`. Option D is wrong because the code is syntactically valid and runs without error; `print('100')` is a standard Python statement.

92
Multi-Selectmedium

Which THREE are valid ways to create a multiline string in Python?

Select 3 answers
A.s = ('Line1\n' 'Line2')
B.s = """Line1 Line2"""
C.s = '''Line1 Line2'''
D.s = "Line1\ Line2"
E.s = 'Line1 Line2'
AnswersA, B, C

This is correct because Python implicitly concatenates adjacent string literals at compile time. The expression ('Line1\n' 'Line2') produces the single string 'Line1\nLine2', where \n is a single escape character representing a line break. When printed, the result appears on two lines, so it is a valid multiline string. The parentheses are not required but help break long lines for readability.

Why this answer

Options A, B, and C are all valid ways to create a multiline string in Python. Option A uses implicit string concatenation within parentheses; the `\n` escape sequence inserts a newline, resulting in a multiline string. Option B uses triple double quotes to span multiple lines physically, preserving line breaks.

Option C uses triple single quotes, which work identically to triple double quotes for multiline strings. Option D uses a backslash for line continuation, which does not insert a newline into the string—it just continues the literal on the next line, so the result is a single-line string without a newline. Option E causes a syntax error because a single-quoted string literal cannot span multiple lines without a continuation character.

Exam trap

Python Institute often tests the distinction between physical line continuation (backslash) and actual multiline string creation (triple quotes or implicit concatenation with `\n`), trapping candidates who think a backslash at line end produces a multiline string.

93
Multi-Selecthard

Given s = 'a1b2c3', which TWO of the following expressions return the string '123'?

Select 2 answers
A.s[0:5:2]
B.s[1::2]
C.s[1:6:2]
D.s[0::2]
E.s[2:5:1]
AnswersB, C

s[1::2] begins at index 1 (the first digit character '1') and then takes every second character thereafter, with no explicit stop so it runs to the end of the string. Indices 1, 3, and 5 correspond to '1', '2', and '3', respectively, so the result is exactly '123'. This is the correct expression because it isolates the digits that are positioned at odd indices.

Why this answer

Slicing with `s[1::2]` starts at index 1 (the character '1'), goes to the end of the string, and takes every second character, resulting in '1', '2', '3' concatenated as '123'. Option C is also correct because `s[1:6:2]` starts at index 1, stops before index 6 (the string length is 6, so index 6 is just past the last character), and steps by 2, yielding the same sequence of characters.

Exam trap

Python Institute often tests the misconception that slicing with a step of 2 always starts from index 0, causing candidates to overlook the correct starting index needed to isolate digits from a mixed string.

94
MCQhard

A company has a large Python application that uses multiple packages from different directories. The application's main entry point is at /opt/app/main.py. There is a package 'common' located at /opt/app/common/ and another package 'services' at /opt/app/services/. Both packages have __init__.py files. Additionally, there is a third-party package 'utils' installed in the system site-packages. Recently, a developer added a new module 'helpers.py' to the 'common' package. When trying to import 'common.helpers' from a script inside 'services', an ImportError is raised: 'No module named common.helpers'. However, importing 'common' itself works. The sys.path includes /opt/app/ and the site-packages. What is the most likely cause of the import failure?

A.The 'helpers.py' file was added after the Python interpreter started, and sys.modules caching prevents new imports.
B.There is another 'common' package elsewhere in sys.path that shadows the intended one, and the shadowed package does not have a 'helpers' submodule.
C.The PYTHONPATH environment variable is not set, so the /opt/app/ directory is not searched.
D.The 'common' package itself is already imported and cached, so adding a new module does not become visible.
AnswerB

This is the correct explanation. Python searches the directories and zip files listed in sys.path in order, and for a dotted import like 'common.helpers', it looks for a package (a directory with __init__.py) named 'common' in each path entry. If an earlier sys.path entry contains a different 'common' package that lacks a 'helpers' submodule, Python imports that shadowing package and then attempts to find 'helpers' within it, raising ModuleNotFoundError before ever reaching the intended /opt/app/common/ package. This is a classic path-shadowing bug that causes the real file to be completely ignored.

Why this answer

The most likely cause is that a different 'common' package (without a 'helpers' submodule) appears earlier in sys.path and shadows the intended /opt/app/common/ package. Since sys.path includes /opt/app/ and site-packages, if a 'common' package exists in site-packages or another directory listed before /opt/app/, Python will import that shadowed package instead, and it lacks the newly added 'helpers' module. This explains why importing 'common' succeeds (the shadowed package exists) but 'common.helpers' fails.

Exam trap

Python Institute often tests the subtlety that a package can be shadowed by another package with the same name earlier in sys.path, leading to successful import of the parent but failure for submodules that exist only in the intended package.

How to eliminate wrong answers

Option A is wrong because Python does not automatically cache modules based on file modification time; sys.modules caching only prevents re-importing a module that was already imported, but it does not prevent importing a newly added module if the package was not previously imported. Option C is wrong because the sys.path already includes /opt/app/ (as stated), so PYTHONPATH is not required for that directory to be searched. Option D is wrong because even if 'common' was previously imported, Python's import system checks for new submodules by searching the package's __path__ on disk, not just sys.modules; the issue is not caching but a shadowing conflict.

95
MCQmedium

A developer creates a package 'mypackage' with the following structure: mypackage/ __init__.py module1.py module2.py The __init__.py contains: from mypackage.module1 import func1 from mypackage.module2 import func2 __all__ = ['func1', 'func2'] In a separate script, the developer writes: from mypackage import * print(func1()) This works as expected. However, when the developer runs the same script from a different directory (not the one containing mypackage), the import works but the script prints an error that func1 is not defined. What could be the problem?

A.The current working directory is not in sys.path, so the package cannot be found.
B.The __all__ variable hides func1 because it does not include it, but it does.
C.The mypackage directory lacks proper __init__.py (maybe it is not present or invalid), causing it to be treated as a namespace package, and the __init__.py is never executed.
D.The imports in __init__.py are relative imports and fail when run from a different directory.
AnswerC

For a directory to be a regular package, Python requires a valid `__init__.py`; when that file is missing, Python 3.3+ treats the directory as a namespace package. A namespace package executes no initialization code, so the `from mypackage.func1 import func1` lines that would normally populate the package namespace never run. The package is still importable, but it appears empty — exactly matching the failure to find `func1` while `import mypackage` succeeds.

Why this answer

If the `mypackage` directory is found but its `__init__.py` is missing, invalid, or not executed (e.g., due to being a namespace package in Python 3.3+), the `from mypackage import *` statement will not trigger the imports defined in `__init__.py`. Consequently, `func1` and `func2` are never bound in the package namespace, leading to a `NameError` when the script tries to call `func1()`. This scenario occurs when the package is located via `sys.path` but the `__init__.py` is not properly processed, often because the directory is treated as a namespace package (PEP 420) rather than a regular package.

Exam trap

The PCAP exam often tests the distinction between regular packages (with `__init__.py`) and namespace packages (without `__init__.py` in Python 3.3+), trapping candidates who assume that a directory containing a package structure always executes its `__init__.py` regardless of file presence or validity.

How to eliminate wrong answers

Option A is wrong because the problem states that the import works (i.e., the package is found), so the current working directory must be in `sys.path` or the package is accessible via another path entry; the error occurs after import, not during it. Option B is wrong because `__all__` explicitly includes `'func1'` and `'func2'`, so it does not hide them; in fact, `__all__` controls what `from mypackage import *` exports, and here it correctly lists both functions. Option D is wrong because the imports in `__init__.py` use absolute imports (`from mypackage.module1 import func1`), which are not relative and do not depend on the current working directory; relative imports would use a leading dot (e.g., `from .module1 import func1`).

96
Multi-Selectmedium

Which TWO of the following can be used to remove leading whitespace (spaces, tabs, newlines) from a string? (Choose exactly 2 correct answers.)

Select 2 answers
A.rstrip()
B.lstrip()
C.trim()
D.clean()
E.strip()
AnswersB, E

lstrip() specifically removes leading whitespace.

Why this answer

The `lstrip()` method removes all leading whitespace characters (spaces, tabs, newlines) from the left side of a string. `strip()` removes leading and trailing whitespace, so it also satisfies the requirement of removing leading whitespace. Both are built-in string methods in Python.

Exam trap

Candidates often confuse `rstrip()` with removing leading whitespace because of the 'r' prefix, or incorrectly assume `trim()` or `clean()` are valid Python methods.

97
Multi-Selecthard

Which TWO of the following statements about Python's `sys.path` are true?

Select 2 answers
A.The current working directory is always the first element in `sys.path`.
B.Module search stops at the first matching directory in `sys.path`.
C.`sys.path` is initialized from the PYTHONPATH environment variable.
D.`sys.path` is a tuple of strings.
E.The directory containing the script being run is added to the beginning of `sys.path` at startup.
AnswersB, E

This is true: the import system walks through the directories and zip archives listed in `sys.path` sequentially, and the first entry that contains the requested module (or package) is used; Python does not continue searching later entries for an alternative. This is why the order of `sys.path` is critical—adding a directory to the front can shadow a standard-library module or another installed package. If no matching module is found, an `ImportError` is raised after the entire list has been exhausted.

Why this answer

Python's import mechanism iterates through `sys.path` in order and stops at the first directory containing the requested module. Option E is correct: the directory containing the script (or the current directory when running interactively) is inserted at the beginning of `sys.path` at startup. Options A, C, and D are false: the current working directory is not always first (the script's directory takes precedence), `sys.path` is initialized from the `PYTHONPATH` environment variable *in addition to* default paths, and `sys.path` is a list, not a tuple.

Therefore, only two statements are true.

Exam trap

The Python Institute often tests that `sys.path` is a list, not a tuple, and that the script's directory, not the current working directory, is inserted first. Candidates may mistakenly think `PYTHONPATH` is the sole source of `sys.path` initialization, but it is only one of several sources.

98
MCQhard

A Python package 'mypackage' contains the following hierarchy: mypackage/ __init__.py subpackage1/ __init__.py module_a.py subpackage2/ __init__.py module_b.py From a script outside the package, a programmer writes: import mypackage.subpackage1.module_a Which statement is true about the import?

A.Only mypackage/__init__.py is executed.
B.No __init__.py files are executed because the import uses a dotted path.
C.After the import, 'mypackage' is not available as a name in the namespace.
D.Both mypackage/__init__.py and mypackage/subpackage1/__init__.py are executed.
AnswerD

When importing `mypackage.subpackage1`, Python executes the `__init__.py` of each package along the dotted path to initialize them as proper packages. This happens because the import system processes each component sequentially: first `mypackage` is imported, which runs its `__init__.py`, then its submodule `subpackage1` is imported, which runs its own `__init__.py`. This two-step initialization is fundamental to Python's package system, ensuring parent packages are fully loaded before their subpackages.

Why this answer

When Python encounters an import statement with a dotted path like `import mypackage.subpackage1.module_a`, it executes the `__init__.py` files for each package in the path in order: first `mypackage/__init__.py`, then `mypackage/subpackage1/__init__.py`. This is because Python must initialize each package before it can access its subpackages or modules. Option D correctly states that both `__init__.py` files are executed.

Exam trap

Python Institute often tests the misconception that dotted imports skip `__init__.py` execution or that only the final module is loaded, when in fact Python executes every `__init__.py` along the dotted path to ensure proper package initialization.

How to eliminate wrong answers

Option A is wrong because Python does not stop at the top-level package; it must also execute `subpackage1/__init__.py` to initialize that subpackage before importing `module_a`. Option B is wrong because `__init__.py` files are always executed when their corresponding package is imported, regardless of whether the import uses a dotted path or a direct package name. Option C is wrong because after `import mypackage.subpackage1.module_a`, the name `mypackage` is bound in the namespace as a reference to the top-level package object, allowing access via `mypackage.subpackage1.module_a`.

99
MCQeasy

Which of the following is a valid way to import a module named 'math' and assign it an alias 'm'?

A.alias math as m
B.from math import * as m
C.import m from math
D.import math as m
AnswerD

`import math as m` is the correct and idiomatic way to import the `math` module while binding it to the local name `m`. The `as` clause in an import statement creates an alias for the module object, so every subsequent reference to `m` (such as `m.sqrt(2)`) accesses the `math` module's functionality without needing to type the full module name. This is a standard feature of the import system, commonly used to shorten long module names or avoid name conflicts.

Why this answer

Python's `import` statement allows you to import a module and assign it an alias using the `as` keyword, as in `import math as m`. This creates a reference to the `math` module under the name `m`, so you can call functions like `m.sqrt(16)` without polluting the namespace with the original module name.

Exam trap

Python Institute often tests the misconception that `alias` is a Python keyword or that `from ... import *` can be combined with `as`, leading candidates to pick options A or B instead of the correct `import ... as ...` syntax.

How to eliminate wrong answers

Option A is wrong because `alias` is not a valid Python keyword; the correct syntax uses `import ... as ...`, not `alias`. Option B is wrong because `from math import *` imports all names from the module into the current namespace, and the `as m` clause is not allowed with the `from ... import *` form; aliasing is only supported with a single imported name or module. Option C is wrong because the syntax `import m from math` is invalid; Python requires the module name to come immediately after `import`, and the alias (if any) must follow the `as` keyword.

100
MCQmedium

An application uses a class to represent a configuration object that reads settings from a file. The class has a class attribute config_cache that holds a dictionary of loaded configurations to avoid repeated file reads. However, the developer notices that when they modify the dictionary for one instance, it affects all instances. They want to ensure that each instance has its own copy of the configuration data upon initialization. Which change should they make?

A.Move the dictionary initialization into the __init__ method so each instance creates its own dictionary.
B.Use a @staticmethod to return a new dictionary each time.
C.Keep the class attribute but use a deep copy in __init__ before modifying.
D.Define the dictionary inside a class method.
AnswerA

Initializing in __init__ creates a new dictionary per instance, avoiding sharing.

Why this answer

Moving the dictionary initialization into the __init__ method ensures that each instance gets its own separate dictionary object. Class attributes are shared across all instances, so modifying the dictionary via one instance changes it for all. By assigning `self.config_cache = {}` inside __init__, each instance creates a new, independent dictionary upon instantiation, solving the shared-state problem.

Exam trap

Python Institute often tests the distinction between mutable and immutable class attributes, trapping candidates who think a deep copy in __init__ will fix the sharing issue, when in fact the shared reference to the class attribute itself must be replaced with an instance attribute.

How to eliminate wrong answers

Option B is wrong because a @staticmethod that returns a new dictionary would still need to be called and assigned to an instance attribute; if the result is stored in a class attribute, the sharing issue persists. Option C is wrong because using a deep copy in __init__ before modifying does not prevent the initial shared reference; the class attribute itself remains a single dictionary that all instances point to, so any modification to the original (or a copy made later) still affects the shared object. Option D is wrong because defining the dictionary inside a class method does not change its scope; if the method assigns to a class attribute, it remains shared, and if it returns a new dict, the instance must still store it properly to avoid sharing.

101
MCQmedium

A Python script placed in /opt/myapp/script.py fails with ImportError when run from a cron job with the command: python /opt/myapp/script.py. The script works when run manually from the /opt/myapp/ directory. The script contains the line: from . import config. The config module is located in /opt/myapp/lib/config.py with an __init__.py in /opt/myapp/lib/. What is the most likely cause of the failure?

A.The __init__.py file in the lib directory is empty and should contain imports.
B.The lib directory is not in sys.path when the script is run from cron.
C.Relative imports are not allowed in a script that is executed directly because its __name__ is not set to a package name.
D.The cron job uses a different Python interpreter that does not have the required standard library.
AnswerC

When a script is run directly, it is treated as __main__, not as part of a package, so relative imports fail.

Why this answer

When a Python script is executed directly (e.g., `python /opt/myapp/script.py`), its `__name__` is set to `'__main__'`, not to a package name. Relative imports (like `from . import config`) require the importing module to be part of a package with a proper `__name__` reflecting the package hierarchy. Since the script is run as the top-level entry point, the relative import fails with an `ImportError`.

This explains why the script works when run manually from `/opt/myapp/` (if the working directory is set appropriately, but the relative import still fails unless the script is run as a module with `-m`), but fails from cron where the working directory is typically the user's home directory.

Exam trap

Python Institute often tests the distinction between running a script directly (`python script.py`) versus running it as a module (`python -m package.script`), and the trap here is that candidates mistakenly blame `sys.path` or `__init__.py` contents instead of recognizing that relative imports are fundamentally incompatible with direct script execution.

How to eliminate wrong answers

Option A is wrong because an empty `__init__.py` is sufficient to mark a directory as a Python package; it does not need to contain imports. The error is not caused by the contents of `__init__.py`. Option B is wrong because the `lib` directory is not directly in `sys.path`; however, the relative import `from . import config` does not rely on `sys.path` — it relies on the package structure and the `__name__` of the script.

The script's failure is not due to missing `sys.path` entries, but due to the prohibition of relative imports in a directly executed script. Option D is wrong because the cron job uses the same Python interpreter as the manual run (both invoke `python`), and the error is an `ImportError` specific to relative imports, not a missing standard library module.

102
MCQmedium

A team is implementing a shape hierarchy with a base class `Shape` that should have an `area()` method. They want to ensure that every subclass must provide its own implementation of `area()`. Which approach should they use?

A.Define `area()` in `Shape` and have it raise `NotImplementedError`.
B.Use a class method that must be overridden.
C.Define `area()` as a property that raises an error.
D.Use `@abstractmethod` from the `abc` module to declare `area()` as abstract.
AnswerD

Decorating `area()` with `@abstractmethod` inside an `ABC` subclass installs `ABCMeta` as the metaclass, which tracks the class's `__abstractmethods__` set. If any abstract method remains unimplemented, `ABCMeta.__call__` refuses to instantiate the class (`TypeError`), and any concrete subclass must override `area()` (or remain abstract itself). This gives construction-time enforcement rather than deferring errors to method calls.

Why this answer

The `abc` module provides the `ABCMeta` metaclass and the `@abstractmethod` decorator, which together enforce that any concrete subclass must override the abstract method. If a subclass fails to implement `area()`, Python raises a `TypeError` at instantiation time, ensuring the design contract is upheld. This is the standard Pythonic way to define abstract base classes and enforce method implementation in subclasses.

Exam trap

Python Institute often tests the distinction between raising `NotImplementedError` (a runtime-only check) and using `@abstractmethod` (which prevents instantiation of incomplete subclasses), leading candidates to mistakenly choose Option A because they think 'raising an error' is sufficient for enforcement.

How to eliminate wrong answers

Option A is wrong because raising `NotImplementedError` at runtime does not enforce compile-time or instantiation-time checks; a subclass can forget to override `area()` and the error will only appear when the method is called, not when the object is created. Option B is wrong because a class method (`@classmethod`) is not designed for abstract method enforcement; it can be overridden but there is no built-in mechanism to require overriding, and the `@abstractmethod` decorator is the correct tool for that purpose. Option C is wrong because defining `area()` as a property that raises an error does not prevent instantiation of a subclass that fails to override the property; the error only occurs when the property is accessed, and properties are not intended for abstract method enforcement.

103
MCQmedium

Consider a class `D` that inherits from multiple base classes `B` and `C`. The developer wants to call a method from a specific parent class while ensuring correct method resolution order (MRO). Which is the safest way?

A.`self.method()`
B.`ParentClass.method(self)`
C.`super().method()`
D.`BaseClass.method(self)`
AnswerC

`super().method()` delegates to the next class in the MRO after the current class, not necessarily the immediate parent, which is exactly what cooperative multiple inheritance requires. Python computes the MRO using the C3 linearization algorithm, so every ancestor appears exactly once and after each class's call to `super()`, the chain continues in the correct order. This ensures shared base classes are processed only once and remains correct even when the hierarchy changes.

Why this answer

In Python, `super().method()` is the safest way to call a method from a parent class in a multiple inheritance scenario because it respects the Method Resolution Order (MRO) defined by the C3 linearization algorithm. This ensures that the method is resolved from the next class in the MRO, avoiding hard-coded references that could break if the inheritance hierarchy changes. It also correctly handles cooperative multiple inheritance, where each class in the MRO can collaborate via `super()` calls.

Exam trap

Python Institute often tests the misconception that `super()` only calls the immediate parent class, when in fact it follows the full MRO, and candidates mistakenly choose a hard-coded parent call (like Option B or D) thinking it is more explicit and safer.

How to eliminate wrong answers

Option A is wrong because `self.method()` will invoke the method on the instance using the MRO, starting from the class of `self`, which may not call the intended parent class method if the method is overridden in a subclass. Option B is wrong because `ParentClass.method(self)` is a hard-coded reference that bypasses the MRO entirely, leading to potential issues in diamond inheritance or if the class hierarchy is modified. Option D is wrong because `BaseClass.method(self)` is essentially the same as Option B — it directly calls a specific base class method, ignoring the MRO and breaking cooperative multiple inheritance patterns.

104
MCQmedium

You are a developer for an e-commerce platform. The system receives product descriptions from suppliers in various formats. One supplier sends descriptions with inconsistent capitalization, extra whitespace, and occasional leading/trailing punctuation. Your task is to write a function that normalizes these descriptions: convert to lowercase, remove leading/trailing whitespace and punctuation (.,!?;:), and replace multiple spaces with a single space. The function should return the cleaned string. Which implementation correctly performs all these steps?

A.def normalize(s): import re; s = s.strip(); s = s.strip('.,!?;:'); s = s.lower(); s = re.sub(r'\s+', ' ', s); return s
B.def normalize(s): return ' '.join(s.lower().split())
C.def normalize(s): return s.lower().strip('.,!?;: ')
D.def normalize(s): return s.strip().lower()
AnswerA

The correct implementation first trims surrounding whitespace with s.strip(), then removes any leading/trailing punctuation characters via s.strip('.,!?;:') — a subtle but important order, because punctuation attached after spaces (e.g., " hello! ") is only exposed for removal after the outer whitespace is gone. Lowercasing follows, and finally re.sub(r'\s+', ' ', s) collapses any runs of internal whitespace (tabs, newlines, multiple spaces) into a single space. This sequence yields a fully canonical form: " Hello, World!! " becomes "hello, world". It deliberately handles each normalization dimension independently, making the result predictable for exact-match comparisons.

Why this answer

It performs all required steps in the correct order: it first strips leading/trailing whitespace with `strip()`, then removes leading/trailing punctuation using `strip('.,!?;:')`, converts to lowercase with `lower()`, and finally replaces multiple spaces with a single space using `re.sub(r'\s+', ' ', s)`. This ensures that punctuation is removed only from the edges after whitespace is handled, and internal whitespace is normalized last.

Exam trap

Python Institute often tests the order of operations in string normalization, and the trap here is that candidates may think `strip()` with a punctuation argument also handles whitespace or that `split()` and `join()` alone are sufficient to remove punctuation, leading them to choose options that miss one or more required steps.

How to eliminate wrong answers

Option B is wrong because it uses `split()` which splits on any whitespace and removes it entirely, but it does not remove leading/trailing punctuation (e.g., '!Hello' becomes '!hello' after `lower()` and split/join, leaving the exclamation mark). Option C is wrong because `strip('.,!?;: ')` removes only leading/trailing characters from that set, but it does not replace multiple internal spaces with a single space (e.g., 'Hello World' stays with multiple spaces). Option D is wrong because it only strips whitespace and lowercases, ignoring the removal of leading/trailing punctuation and the normalization of multiple internal spaces.

105
MCQhard

Given package structure: pack/__init__.py, pack/subpack/__init__.py, pack/subpack/mod.py. Inside pack/__init__.py, which import statement correctly imports mod.py using a relative import?

A.from . import subpack.mod
B.from subpack import mod
C.from ..subpack import mod
D.from .subpack import mod
AnswerD

The leading dot indicates a relative import from the current package (`pack`). This statement imports the `mod` submodule from the `subpack` subpackage that is a child of the current package. This is the standard way to import a module from a sibling subpackage in a package, ensuring the import is resolved relative to the current package's location, not the top-level `sys.path`.

Why this answer

`from .subpack import mod` uses a leading dot to indicate a relative import from the current package (`pack`), then navigates into `subpack` and imports `mod`. This is the proper syntax for importing a module from a subpackage within the same parent package.

Exam trap

Python Institute often tests the distinction between absolute and relative imports, and the trap here is that candidates mistakenly use an absolute import (Option B) or incorrect dot syntax (Option A or C) because they confuse the number of dots or the placement of the module name in the import statement.

How to eliminate wrong answers

Option A is wrong because `from . import subpack.mod` is invalid syntax; relative imports require the dot to be followed directly by a package or module name, not a dotted path after the import keyword. Option B is wrong because `from subpack import mod` is an absolute import, which would look for a top-level package named `subpack`, not the one inside `pack`. Option C is wrong because `from ..subpack import mod` uses two dots, which would go up one level from `pack` to its parent, not down into `subpack`.

106
Drag & Dropmedium

Drag and drop the steps to perform unit testing with the unittest framework in Python into the correct order.

Drag steps to the numbered slots on the right, or tap a step then tap a slot.

Steps
Order
1Step 1
2Step 2
3Step 3
4Step 4

Why this order

Unit testing with unittest requires importing, creating a TestCase subclass, writing test methods, and calling unittest.main().

107
MCQmedium

A logging module receives a message that may contain sensitive data. To comply with data privacy, all digits in the message should be replaced with 'X' before logging. Which approach correctly achieves this?

A.message.replace('0-9', 'X')
B.re.sub(r'[0-9]', 'X', message)
C.message.translate(str.maketrans('0123456789', 'XXXXXXXXXX'))
D.''.join(['X' if c.isdigit() else c for c in message])
AnswerB, C, D

This invokes re.sub with the pattern [0-9], a character class that matches exactly one character from the range '0' through '9'. Each matched digit is replaced independently with 'X', so the entire message is scanned and every digit becomes an X. Because re.sub processes the whole string and replaces all non-overlapping matches, this correctly sanitizes all ASCII digits in the message.

Why this answer

Options B, C, and D all correctly replace all digits in the message with 'X'. Option B uses `re.sub()` with a regex character class to match any digit. Option C uses `str.translate()` with a mapping from each digit to 'X', which works because the mapping explicitly covers all digits.

Option D uses a list comprehension with `isdigit()` to conditionally replace digits. Option A is incorrect because `str.replace()` does not interpret character ranges; it would look for the literal string '0-9'. Therefore, three correct approaches exist.

Exam trap

Candidates may assume only `re.sub()` is correct, but `str.translate()` with explicit mapping and list comprehension with `isdigit()` also achieve the same result. The exam may expect recognition that multiple Python methods can accomplish the same task.

How to eliminate wrong answers

Option A is wrong because `message.replace('0-9', 'X')` treats the string `'0-9'` as a literal substring to replace, not as a range of digits; it will only replace the exact sequence '0-9' if it appears in the message. Option C is wrong because `str.maketrans('0123456789', 'XXXXXXXXXX')` creates a translation table that maps each digit character to 'X', but `message.translate()` returns a new string with the replacements applied; while this would technically work, it is not the most direct or idiomatic approach for this task, and the question asks for the approach that 'correctly achieves this' — Option B is more standard and less error-prone. Option D is wrong because it uses a list comprehension with `c.isdigit()` to replace digits with 'X', which is functionally correct but is not a method of the string class; it is a valid Python expression but not a string method, and the question implies using a string method or a direct replacement approach.

108
Multi-Selecthard

Which THREE of the following statements about Python's 'with' statement are true? (Select exactly 3)

Select 3 answers
A.It can be used with any object that implements __enter__ and __exit__ methods.
B.It guarantees that the __exit__ method is called even if an exception occurs inside the block.
C.It can be used with multiple context managers separated by commas.
D.It eliminates the need for try/finally blocks for resource management.
E.It can only be used with file objects.
AnswersA, B, C

That's the context manager protocol.

Why this answer

The 'with' statement in Python is designed to work with any object that implements the context management protocol, which consists of the __enter__ and __exit__ methods. This allows the 'with' statement to manage resources beyond just files, such as database connections, locks, or network sockets, as long as the object provides these two methods.

Exam trap

Python Institute often tests the misconception that the 'with' statement is only for file I/O, leading candidates to incorrectly select option E, while also testing the understanding that it simplifies but does not replace try/finally blocks, making option D a distractor for those who overestimate its capabilities.

109
Drag & Dropmedium

Drag and drop the steps to serialize a Python object to JSON using the json module into the correct order.

Drag steps to the numbered slots on the right, or tap a step then tap a slot.

Steps
Order
1Step 1
2Step 2
3Step 3
4Step 4

Why this order

Serialization to JSON involves importing json, preparing data, using dumps for string or dump for file output.

110
MCQhard

A developer is working on a class hierarchy for geometric shapes. They have a base class Shape with an abstract method area(). They also have a mixin class Drawable that provides a method draw(). They want to create a class Rectangle that inherits from both Shape and Drawable. However, they encounter a TypeError when trying to instantiate Rectangle because the abstract method area() is not implemented. Which action should they take to resolve this?

A.Change the inheritance order to Drawable first, then Shape.
B.Implement the area() method in Rectangle.
C.Use a class decorator @abstractmethod for Rectangle.
D.Remove the abstract method from Shape by removing the @abstractmethod decorator.
AnswerB

All abstract methods must be implemented in a concrete subclass.

Why this answer

The abstract method area() declared in the Shape base class must be implemented in any concrete subclass. In Python, a class that inherits from an ABC (Abstract Base Class) with an abstract method cannot be instantiated until that method is overridden. By providing an implementation of area() in Rectangle, the class becomes concrete and can be instantiated without raising a TypeError.

Exam trap

Python Institute often tests the misconception that changing inheritance order or using decorators can bypass the abstract method requirement, when in fact the only valid fix is to implement the abstract method in the concrete subclass.

How to eliminate wrong answers

Option A is wrong because changing the inheritance order does not affect the requirement to implement abstract methods; the TypeError arises from the missing implementation, not from the MRO. Option C is wrong because @abstractmethod is a decorator used to declare abstract methods, not a class decorator; applying it to Rectangle would make Rectangle itself abstract, not resolve the missing implementation. Option D is wrong because removing the @abstractmethod decorator from Shape would break the design contract, but more importantly, the question asks how to resolve the error while preserving the abstraction; removing the decorator eliminates the requirement but is not the intended solution for a proper class hierarchy.

111
Multi-Selectmedium

Which THREE of the following are true about the `__init__` method in Python?

Select 3 answers
A.It can be called manually.
B.It must return a value.
C.It can accept arguments.
D.It is not inherited.
E.It is called automatically when an instance is created.
AnswersA, C, E

Although __init__ is invoked automatically during instance creation, it is also an ordinary method and can be called manually on an existing instance, such as obj.__init__(new_args). This manually calls the initializer to reset or reinitialize the object's attributes, which can be useful for object reuse or unit testing. The ability to call it manually does not interfere with its automatic invocation; both can coexist. Thus, the statement is true.

Why this answer

The __init__ method is a special method in Python classes used for initializing newly created objects. It can be called manually (e.g., obj.__init__()), it accepts arguments that are passed during instance creation, and it is automatically invoked when an instance is created via the class constructor. It does not require a return value (it returns None), and it is inherited by subclasses unless explicitly overridden.

Exam trap

A common trap is thinking that __init__ cannot be called manually or that it is the constructor (it is an initializer; __new__ is the constructor). Also, some believe __init__ must return a value, but it must return None.

112
MCQmedium

Which of the following demonstrates that strings are immutable?

A.s.upper() changes s in place
B.s[0] = 'J' results in a TypeError
C.s += '!' modifies s
D.s.replace('a','b') modifies s
AnswerB

The statement s[0] = 'J' raises a TypeError because assignment to an indexed position attempts to modify the contents of an existing str object, and immutable objects do not support item assignment. The interpreter explicitly forbids this operation, which is the most direct and unambiguous demonstration of string immutability.

Why this answer

Attempting to assign a new character to an index of a string (e.g., s[0] = 'J') raises a TypeError, which directly demonstrates that strings are immutable in Python. Immutability means the object's value cannot be changed after creation; any operation that appears to modify a string actually creates a new string object.

Exam trap

Python Institute often tests the misconception that methods like upper(), replace(), or the += operator modify the original string in place, when in fact they always return a new string object, and the trap is that candidates confuse variable rebinding with in-place mutation.

How to eliminate wrong answers

Option A is wrong because s.upper() does not change s in place; it returns a new string with all uppercase characters, leaving the original string s unchanged. Option C is wrong because s += '!' does not modify the original string in place; it creates a new string object and rebinds the variable s to that new object, while the original string remains unchanged. Option D is wrong because s.replace('a','b') does not modify s; it returns a new string with the replacements applied, and the original string s is unaffected.

113
MCQhard

A package 'pkg' is installed as an egg-link in development mode. Inside the package, there is a module 'submod.py' that uses relative imports. When a developer modifies 'submod.py', they find that changes are not always reflected on import. What is the most likely reason?

A.The sys.path is altered by the egg-link, causing a different module to be loaded.
B.Relative imports are cached in the __init__.py file.
C.Python's module caching in sys.modules prevents re-loading the modified source.
D.The __pycache__ directory is not cleared automatically.
AnswerC

When a module is first imported, Python stores the resulting module object in `sys.modules` under its full qualified name; every later `import` statement checks `sys.modules` first and returns that same object without re-reading the source file. In an egg-link development environment, the source directory is the one being imported, so you are editing the exact file that was loaded — but the interpreter has already cached the compiled, executed version of that module. You must use `importlib.reload(module)` or restart the process to force reparsing and re-execution of the modified `.py` file.

Why this answer

Python caches imported modules in `sys.modules`. When a module is imported, Python stores the module object in `sys.modules` and subsequent imports retrieve it from this cache without re-executing the module's code. Modifying the source file of `submod.py` does not automatically invalidate this cache, so the changes are not reflected unless the module is explicitly reloaded (e.g., with `importlib.reload()`) or the interpreter is restarted.

Exam trap

Python Institute often tests the distinction between source file modification and module caching, where candidates mistakenly think the issue is with bytecode caching (`__pycache__`) or path resolution, rather than the `sys.modules` cache that prevents re-execution of the module's code.

How to eliminate wrong answers

Option A is wrong because an egg-link installs a development mode package by adding a path to `sys.path` that points to the source directory; it does not cause a different module to be loaded—the same source file is used, but the caching issue still applies. Option B is wrong because relative imports are not cached in `__init__.py`; they are resolved at import time based on the package's `__name__` and `__path__`, and caching occurs in `sys.modules`, not in `__init__.py`. Option D is wrong because `__pycache__` stores bytecode files (`.pyc`) for performance, but Python checks the modification time of the source file against the cached bytecode; if the source is newer, it recompiles—so the issue is not about clearing `__pycache__` but about the module object already being in `sys.modules`.

114
MCQeasy

A developer writes a function that reads a file and processes its content. The function should handle the case where the file does not exist without catching other I/O errors. Which exception should be caught?

A.PermissionError
B.IOError
C.OSError
D.FileNotFoundError
AnswerD

FileNotFoundError is the specific built-in exception that Python raises when an attempt to open or access a file path cannot succeed because the path does not exist, typically with errno ENOENT. For a read operation, open(path, 'r') will immediately raise it if the file is not present before any other processing occurs. Because it is narrowly scoped, catching FileNotFoundError lets the developer provide exactly the right fallback—like creating the file or printing a meaningful message—without masking permission problems or unrelated OS failures.

Why this answer

`FileNotFoundError` is a specific subclass of `OSError` that is raised exactly when a file or directory is requested but does not exist. By catching only `FileNotFoundError`, the function handles the missing-file scenario without masking other I/O errors such as permission issues or disk failures, which is the precise requirement stated in the question.

Exam trap

Python Institute often tests the Python exception hierarchy, and the trap here is that candidates mistakenly choose `IOError` or `OSError` because they are broader and seem 'safer,' but the question explicitly requires handling only the missing-file case without catching other I/O errors.

How to eliminate wrong answers

Option A is wrong because `PermissionError` is raised when the file exists but the process lacks the necessary permissions (e.g., read or write access), not when the file is missing. Option B is wrong because `IOError` is an alias for `OSError` in Python 3 and is too broad; catching it would also catch unrelated I/O errors like permission or disk errors, violating the requirement to avoid catching other I/O errors. Option C is wrong because `OSError` is the parent class for many file-related exceptions (including `FileNotFoundError`, `PermissionError`, etc.); catching it would handle all OS-level errors, not just the missing-file case.

115
MCQmedium

A developer installs a third-party package using pip, but when they try to import it in their script, Python raises a ModuleNotFoundError. The package is definitely installed (pip list shows it). What is the most likely cause?

A.The Python interpreter being used is different from the one where the package was installed.
B.The package name contains a hyphen.
C.The script is in a directory that shadows the package name.
D.The package does not have an __init__.py file.
AnswerA

Pip installs packages into the site-packages directory of the specific Python interpreter that invoked it, e.g., when using `python -m pip` versus a different interpreter. If the script runs under another interpreter—such as a different virtual environment, a system Python, or an IDE's bundled runtime—that interpreter's `sys.path` won't include the package's location, producing an ImportError. This is the classic environment-mismatch cause.

Why this answer

When a package is installed via pip, it is placed into the site-packages directory of a specific Python interpreter. If the developer runs their script with a different Python interpreter (e.g., one from a virtual environment, a different version, or a system Python vs. a user-installed Python), that interpreter's import system will not search the site-packages where the package was installed, resulting in a ModuleNotFoundError even though pip list shows the package. This is the most common cause of such a mismatch.

Exam trap

Python Institute often tests the misconception that a package name with a hyphen is invalid for import, leading candidates to choose option B, but the real issue is interpreter mismatch, which is the most common and subtle cause of ModuleNotFoundError in multi-interpreter environments.

How to eliminate wrong answers

Option B is wrong because Python's import system automatically converts hyphens in package names to underscores (e.g., pip install my-package allows import my_package), so a hyphen in the package name does not cause a ModuleNotFoundError. Option C is wrong because a script shadowing a package name would cause an ImportError or unexpected behavior only if the script's directory contains a module or package with the same name as the imported package, but it would not produce a ModuleNotFoundError; the error would be a different one (e.g., AttributeError or incorrect import). Option D is wrong because __init__.py is only required for regular packages in Python 3.3+ for namespace packages or for packages that need initialization code; third-party packages installed via pip are typically regular packages or namespace packages that work without __init__.py, and its absence does not cause a ModuleNotFoundError.

116
MCQhard

A developer runs 'pip install mypackage' but gets a 'PermissionError'. Which command should be used to install the package for the current user only?

A.sudo pip install mypackage
B.pip install --user mypackage
C.pip install --ignore-installed mypackage
D.pip install --target mypackage
AnswerB

This is correct because the --user flag makes pip install the package into the current user's private site-packages directory (e.g., ~/.local/lib/python3.x/site-packages), which is owned by that user and therefore requires no elevated permissions. It resolves the permission error without altering system Python packages, and the directory is automatically included in sys.path by default. This is a safe, supported way to install packages when you lack administrative rights, though virtual environments are often preferred for isolation.

Why this answer

The `--user` flag instructs pip to install the package into the user's site-packages directory (e.g., `~/.local/lib/pythonX.Y/site-packages` on Unix), which does not require elevated permissions. This avoids the `PermissionError` that occurs when pip tries to write to the system-wide site-packages directory (e.g., `/usr/lib/python3/dist-packages`) without administrator privileges.

Exam trap

Python Institute often tests the misconception that `sudo` is the correct way to fix permission errors in pip, but the exam expects candidates to know the safer, user-scoped `--user` flag as the proper solution for installing packages without administrative rights.

How to eliminate wrong answers

Option A is wrong because `sudo pip install mypackage` runs pip with superuser privileges, which bypasses the permission error but is strongly discouraged as it can corrupt the system Python environment and bypass security checks. Option C is wrong because `--ignore-installed` tells pip to ignore already installed packages and reinstall, but it does not change the installation target directory, so the permission error would still occur. Option D is wrong because `--target mypackage` specifies a custom installation directory (e.g., `./mypackage`) but does not resolve the underlying permission issue; it would still fail if the target directory is not writable or is misused as a package name.

117
Multi-Selecthard

Which TWO statements about Python's name mangling are correct?

Select 2 answers
A.Name mangling applies to all method names that start with a single underscore.
B.The mangled name format is _ClassName__attribute.
C.Name mangling prevents external code from accessing the attribute entirely.
D.Name mangling is applied to attributes that start with two underscores but do not end with two underscores.
E.Name mangling occurs at runtime.
AnswersB, D

When an identifier with two leading underscores appears inside a class body, the compiler rewrites it by prefixing a single underscore and the class name: __attr becomes _ClassName__attr. This renaming applies to every lexical occurrence of that identifier within the class definition, so methods that reference the attribute are also rewritten. This is exactly why the mangled format is _ClassName__attribute.

Why this answer

Python's name mangling transforms an attribute name like `__attribute` defined in a class `MyClass` into `_MyClass__attribute`. This mechanism is specifically designed to avoid name clashes in subclasses, not to enforce privacy. The transformation is done by the compiler at definition time, not at runtime.

Exam trap

Python Institute often tests the misconception that name mangling provides true access control (like private in Java), when in fact it is only a name transformation that can be bypassed by using the mangled name directly.

118
Multi-Selecthard

Which THREE methods return a boolean value?

Select 3 answers
A.str.upper()
B.str.startswith()
C.str.islower()
D.str.isalpha()
E.str.find()
AnswersB, C, D

Returns True or False.

Why this answer

B is correct because str.startswith() returns True if the string starts with the specified prefix, otherwise False. It is a boolean-returning method, as required by the question.

Exam trap

Python Institute often tests the distinction between methods that return a boolean versus those that return a new string or an integer, leading candidates to mistakenly select str.upper() or str.find() because they think any method that checks a condition returns a boolean.

119
MCQmedium

A developer is working on a logging system where dynamic values are inserted into a template string. The template is 'User %s logged in at %s'. The developer has the username and timestamp as separate variables. Which approach is most Pythonic (PEP 498) and recommended for new code?

A.Use %-formatting: 'User %s logged in at %s' % (username, timestamp)
B.Use .format(): 'User {} logged in at {}'.format(username, timestamp)
C.Concatenate: 'User ' + username + ' logged in at ' + timestamp
D.Use an f-string: f'User {username} logged in at {timestamp}'
AnswerD

The f-string (formatted string literal) is the recommended formatting method in Python 3.6+ because it allows expressions to be embedded directly inside braces exactly where the value belongs in the text. It is concise, readable, and evaluated at runtime, so it can call functions, index collections, or access attributes without extra method calls. PEP 498 and the official Python documentation endorse f-strings as the preferred form for new code.

Why this answer

PEP 498 introduced f-strings (formatted string literals) as the recommended approach for string formatting in Python 3.6+. They are concise, readable, and evaluated at runtime, allowing direct embedding of expressions. This aligns with the 'Pythonic' principle of simplicity and is the preferred style for new code according to the official Python documentation.

Exam trap

The PCAP exam often tests the distinction between 'most Pythonic' and 'works correctly' — candidates may pick .format() because it is familiar, but PEP 498 explicitly recommends f-strings for new code, making them the correct answer in a PCAP context.

How to eliminate wrong answers

Option A is wrong because %-formatting is the old-style C-like printf approach, which is less readable and not recommended for new code per PEP 498. Option B is wrong because .format() is more verbose and less direct than f-strings, though still valid; it is not the most Pythonic for simple variable interpolation. Option C is wrong because string concatenation is inefficient (creates multiple intermediate strings) and less readable, violating Pythonic principles of clarity and simplicity.

120
MCQhard

A Python class 'Shape' defines an abstract method 'area'. Subclasses 'Circle' and 'Square' implement 'area'. A function 'calculate_area(shape)' expects a 'Shape' instance. Which principle ensures that the function works correctly without knowing the specific subclass?

A.Interface Segregation Principle
B.Liskov Substitution Principle
C.Single Responsibility Principle
D.Dependency Inversion Principle
AnswerB

The Liskov Substitution Principle (LSP) asserts that any subclass must be able to replace its base class without altering the correctness of the program. When Shape declares an abstract area() method, it establishes a behavioral contract that every subclass must honor; if a subclass overrides area() with an incompatible return type, raises an unexpected exception, or changes invariants, it breaks substitutability. This is exactly the design concern addressed by LSP, making it the correct principle for the described scenario.

Why this answer

The Liskov Substitution Principle (LSP) states that objects of a superclass should be replaceable with objects of its subclasses without affecting the correctness of the program. In this scenario, 'calculate_area(shape)' accepts a 'Shape' instance, and because both 'Circle' and 'Square' are proper subtypes that honor the contract of the 'area' method, the function works correctly regardless of which subclass is passed. This is the core of LSP: substitutability without side effects.

Exam trap

Python Institute often tests LSP by presenting a scenario where a subclass overrides a method in a way that changes the expected behavior (e.g., raising an exception or returning a different type), and candidates mistakenly choose Interface Segregation or Dependency Inversion because they confuse 'substitutability' with 'abstraction' or 'interface design'.

How to eliminate wrong answers

Option A is wrong because the Interface Segregation Principle (ISP) focuses on splitting large interfaces into smaller, specific ones so that clients only depend on methods they use; it does not address the substitutability of subclasses in a function parameter. Option C is wrong because the Single Responsibility Principle (SRP) dictates that a class should have only one reason to change, which is unrelated to polymorphic behavior across subclasses. Option D is wrong because the Dependency Inversion Principle (DIP) deals with depending on abstractions rather than concretions, but it does not specifically ensure that a subclass can be used in place of its parent class without breaking functionality—that is LSP's role.

121
MCQhard

A developer writes: s = 'abc'; s[0] = 'x'. What happens?

A.s becomes 'xbc'
B.TypeError: 'str' object does not support item assignment
C.ValueError: string index out of range
D.s becomes 'abc' and no error
AnswerB

This is the exact error raised.

Why this answer

In Python, strings are immutable, meaning their contents cannot be changed after creation. Attempting to assign a new character to an index position (e.g., `s[0] = 'x'`) raises a `TypeError: 'str' object does not support item assignment`. This is a fundamental property of the `str` type in Python, enforced at the interpreter level.

Exam trap

Python Institute often tests the immutability of strings by presenting an assignment to an index, tricking candidates who confuse strings with mutable sequences like lists.

How to eliminate wrong answers

Option A is wrong because it assumes strings are mutable like lists, but Python strings are immutable and cannot be modified in-place. Option C is wrong because the index 0 is valid for a string of length 3, so no `IndexError` or `ValueError` occurs; the error is about assignment, not indexing. Option D is wrong because Python does not silently ignore invalid assignments; it raises an exception immediately.

122
Multi-Selecthard

Which THREE of the following escape sequences are valid in a Python string and represent a single character? (Select exactly three.)

Select 3 answers
A.\x
B.\q
C.\'
D.\\
E.\n
AnswersC, D, E

Single quote escape.

Why this answer

The backslash followed by a single quote (\') is a valid escape sequence in Python that represents a literal single quote character, allowing it to appear inside a single-quoted string without terminating the string. This sequence is interpreted as a single character by the Python parser.

Exam trap

The PCAP exam often tests the distinction between valid and invalid escape sequences, and the trap here is that candidates may assume any backslash-letter combination (like \q) is valid, or that \x alone is sufficient, when in fact only a fixed set of sequences are recognized and incomplete sequences cause a SyntaxError.

123
MCQmedium

Refer to the exhibit. Which of the following is the most likely cause of this error?

A.The __init__.py file in mypackage is empty.
B.There is a circular import between mypackage and mymodule.
C.mymodule.py does not exist in mypackage directory.
D.mypackage is a module file, not a package directory.
AnswerD

When mypackage is a single-file module, it contains no namespace for submodules, so `from mypackage import mymodule` treats mymodule as an attribute that must exist in that file. Since no such attribute is defined, the import machinery raises `ImportError: cannot import name 'mymodule' from 'mypackage'` with the file location of the module. This is the most likely cause because the traceback location is the mypackage module itself, not a package directory, and it aligns with how Python distinguishes modules from packages.

Why this answer

The error indicates that Python cannot import 'mypackage' as a package. If 'mypackage' is a single module file (e.g., mypackage.py) rather than a directory containing an __init__.py file, Python treats it as a module, not a package. This prevents the expected package-style import of submodules like 'mymodule', causing the ImportError.

Exam trap

Python Institute often tests the distinction between a package (directory with __init__.py) and a module (single .py file), trapping candidates who assume any directory can be imported as a package without the required __init__.py marker.

How to eliminate wrong answers

Option A is wrong because an empty __init__.py file is perfectly valid and still marks the directory as a Python package; the error would not occur solely due to an empty __init__.py. Option B is wrong because a circular import typically raises an ImportError with a different traceback (e.g., partially initialized module), not the specific error shown. Option C is wrong because if mymodule.py did not exist, the error would be 'ModuleNotFoundError: No module named mypackage.mymodule', not the generic ImportError about mypackage itself.

124
MCQmedium

Refer to the exhibit. Given the project structure, which of the following import statements in main.py would cause an ImportError?

A.from utils import strings
B.from ..utils import helpers
C.from utils import helpers
D.from utils.strings import format
AnswerB

The leading double dot in from ..utils import helpers marks this as a relative import that climbs one level above the current package. If this line appears in main.py at the project root, main.py is being executed as the __main__ module rather than as an importable package member, so its __package__ is empty and there is no parent package to resolve the dots. This raises ImportError: attempted relative import with no known parent package, which is exactly why this is the only statement that fails and the correct answer.

Why this answer

Uses a relative import with '..' which is only valid inside a package (i.e., when the module is loaded as part of a package and has a __package__ attribute set). In a flat project structure where main.py is a top-level script, '..' attempts to go above the top-level package, which is not allowed and raises an ImportError. Python's import system requires that relative imports be used only within a package hierarchy.

Exam trap

Python Institute often tests the distinction between absolute and relative imports, trapping candidates who assume that '..' works in any script, when in fact relative imports are only valid inside a package and fail with an ImportError when used in a top-level script.

How to eliminate wrong answers

Option A is wrong because 'from utils import strings' is a valid absolute import that works when utils is a package (directory with __init__.py) containing a strings module; no ImportError occurs. Option C is wrong because 'from utils import helpers' is also a valid absolute import if helpers is a module or subpackage within utils; it does not cause an ImportError. Option D is wrong because 'from utils.strings import format' is a valid absolute import that imports the name 'format' from the strings module inside utils; as long as the module exists and contains that name, no ImportError occurs.

125
MCQmedium

You are a Python developer working on a project with the following structure: myapp/ __init__.py main.py modules/ __init__.py utils.py helpers.py The file main.py contains: from modules import utils from modules import helpers utils.some_function() helpers.another_function() When you run main.py, you get an ImportError: No module named 'modules'. However, the modules directory exists and both __init__.py files are present. The directory myapp is not installed as a package; you are running main.py directly from the myapp directory. What is the most likely cause and how should you fix it?

A.Move main.py to the parent directory of myapp and use 'from myapp.modules import utils' or run with 'python -m myapp.main' from the parent.
B.Add the parent directory of myapp to sys.path at the beginning of main.py.
C.Add an __all__ variable in modules/__init__.py to explicitly export the submodules.
D.Rename modules/__init__.py to something else.
AnswerA

This ensures myapp is treated as a package and imports are absolute.

Why this answer

When running main.py directly, Python adds the directory containing main.py (myapp) to sys.path, not its parent. Since 'modules' is a subdirectory of myapp, Python cannot find it as a top-level module. Moving main.py to the parent directory or using the -m flag (which sets the working directory as the script's location) allows 'from myapp.modules import utils' to resolve correctly, as myapp becomes a package.

Exam trap

Python Institute often tests the distinction between running a script directly (which adds the script's directory to sys.path) versus using the -m flag (which adds the current working directory), and candidates mistakenly think that having __init__.py files alone is sufficient for any import style.

How to eliminate wrong answers

Option B is wrong because adding the parent directory of myapp to sys.path would still not make 'modules' importable as a top-level name; Python would need 'from myapp.modules import utils' or a relative import. Option C is wrong because __all__ controls what is exported with 'from module import *', not the ability to import the module itself; the ImportError occurs because 'modules' is not found as a package, not because of missing exports. Option D is wrong because renaming or removing __init__.py would break the package structure entirely, preventing Python from recognizing 'modules' as a package at all.

126
MCQhard

You are a developer at a company that builds a data processing pipeline. The pipeline consists of several Python modules organized in a package called 'pipeline'. The package structure is: pipeline/ __init__.py load.py transform.py analyze.py The pipeline is deployed on a server where Python 3.8 is installed. The server also has a globally installed package called 'pipeline' (from a different project) in the site-packages directory. When you run your scripts that import 'pipeline', you get unexpected behavior because Python is importing the wrong package. You need to ensure that your local 'pipeline' package is used instead of the global one. You cannot uninstall the global package because it is used by another application. You have the following options: A) Modify the PYTHONPATH environment variable to include the directory containing your 'pipeline' package before the site-packages directory. B) Rename your local 'pipeline' package to something else and update all imports. C) Use a virtual environment specific to your project and install your package there. D) Add an __init__.py file with a special import hook to override the global package. Which course of action is the most appropriate and reliable?

A.Modify the PYTHONPATH environment variable to include the directory containing your 'pipeline' package before the site-packages directory.
B.Rename your local 'pipeline' package to something else and update all imports.
C.Use a virtual environment specific to your project and install your package there.
D.Add an __init__.py file with a special import hook to override the global package.
AnswerC

Using a virtual environment creates an isolated environment, ensuring your local package is used without affecting or being affected by the global package. This is the standard and most reliable approach.

Why this answer

Using a virtual environment creates an isolated Python environment where you can install your local 'pipeline' package without affecting or being affected by the globally installed package. This is the most reliable approach as it ensures that Python's import system will search the virtual environment's site-packages before the global site-packages, preventing any naming conflicts. Virtual environments are the standard Python best practice for managing project-specific dependencies and avoiding package name collisions.

Exam trap

The trap here is that candidates often assume modifying PYTHONPATH is a simple and effective solution, but the PCAP exam tests the understanding that PYTHONPATH does not always override site-packages reliably, especially in modern Python versions, making virtual environments the only robust and recommended approach.

How to eliminate wrong answers

Option B is wrong because adding an __init__.py file with a special import hook is not a standard or reliable mechanism to override a global package; Python's import system does not support such hooks in a way that would consistently bypass the global package, and this approach is fragile and non-portable. Option C is wrong because renaming your local package is a workaround that does not solve the underlying import order issue; it also requires updating all imports across the codebase, which is error-prone and does not prevent future conflicts if another package with the same name is installed. Option D is wrong because modifying PYTHONPATH to include your local package directory before site-packages is unreliable; the order of directories in PYTHONPATH is not guaranteed to take precedence over site-packages in all Python versions or configurations, and it can be easily overridden by other environment settings or by the way Python initializes its import path.

127
MCQhard

A class has a class attribute that is a list. A developer modifies this list via one instance, and the change is reflected in all other instances. What is the best practice to avoid this unintended sharing?

A.Use a tuple instead of a list.
B.Initialize the list in `__init__` rather than as a class attribute.
C.Use a class method to modify the list.
D.Use `deepcopy` when accessing the list.
AnswerB

Moving the list into `__init__` as `self.items = ...` causes a brand-new list to be created each time an instance is constructed. Because each object gets its own independent list bound to the instance, changes made through one instance never affect another. This is the standard Python pattern for per-instance mutable state and directly eliminates the accidental sharing caused by a class attribute.

Why this answer

Class attributes are shared across all instances. By initializing the list inside `__init__`, each instance gets its own independent list object, preventing unintended mutation from affecting other instances. This is the standard Python pattern for instance-specific mutable data.

Exam trap

Python Institute often tests the distinction between class-level and instance-level attributes, and the trap here is that candidates mistakenly think using a tuple (immutable) or a class method solves the sharing problem, when the real issue is the location of the mutable object's definition.

How to eliminate wrong answers

Option A is wrong because using a tuple prevents mutation entirely, which is not a solution for the requirement to modify the list; it changes the data structure's semantics and would cause an AttributeError on attempted modification. Option C is wrong because a class method still operates on the class-level list, so modifying it via one instance would still affect all instances; the sharing issue is not about the method type but about where the list is stored. Option D is wrong because `deepcopy` only creates a copy at the time of access, but the underlying class attribute remains shared; repeated accesses would require manual copying each time, which is inefficient and does not solve the fundamental design problem.

128
MCQhard

Refer to the exhibit. A developer ran the script and saw the above traceback. The intended behavior was to load a JSON configuration file, and if the file is missing, create a default config. What is the most likely root cause of the second exception (NameError)?

A.The variable 'f' was not defined due to the FileNotFoundError.
B.The script did not import the json module.
C.The config.json file exists but is empty.
D.The file was opened in binary mode instead of text mode.
AnswerB

NameError: name 'json' is not defined means Python could not find a binding for the name 'json' in any accessible scope. The json module is part of the standard library but is not automatically loaded; it must be brought into scope with an explicit import json statement. Since the script calls json.load(f) without having imported json, the name lookup fails at runtime. This is the classic missing-import error and is unrelated to the file's existence, content, or open mode.

Why this answer

The traceback shows a NameError for 'json.loads', which indicates that the name 'json' is not defined in the current namespace. This occurs when the script attempts to call json.loads() without first importing the json module. The intended behavior of loading a JSON configuration file requires the json module to parse the file content, and its absence causes the NameError exception.

Exam trap

Python Institute often tests the distinction between file I/O exceptions (like FileNotFoundError) and name resolution errors (NameError), trapping candidates who focus on the file handling part of the traceback rather than recognizing that the second exception is about an undefined module name.

How to eliminate wrong answers

Option A is wrong because the NameError occurs after the FileNotFoundError is handled (the traceback shows the exception chain), and the variable 'f' is not referenced in the json.loads() call; the error is about the name 'json', not 'f'. Option C is wrong because an empty file would not cause a NameError; it would cause a json.JSONDecodeError when trying to parse empty content, not a missing name. Option D is wrong because opening a file in binary mode (e.g., 'rb') would not cause a NameError; it would affect how the file content is read (bytes vs string), but the json.loads() function can still be called if the module is imported, and the error would be a TypeError or similar, not a NameError.

129
MCQhard

Consider the following code snippet: s = 'abcdefgh'; result = s[7:3:-2]; print(result). What is the output?

A.fh
B.hf
C.h
D.hfd
AnswerB

With s = 'abcdefgh', the slice s[7:3:-2] starts at index 7 (character 'h'), then subtracts 2 to reach index 5 (character 'f'), and stops before index 3 (character 'd') because the stop is exclusive. The step of -2 reverses the traversal direction and skips every other character. Hence the result is exactly 'hf'—first 'h', then 'f'.

Why this answer

The slice s[7:3:-2] starts at index 7 (character 'h'), goes backwards with step -2, and stops before index 3. The indices visited are 7 and 5, yielding 'h' and 'f', so the result is 'hf'. Option B is correct because the step is negative, meaning the slice moves from right to left, and the stop index is exclusive.

Exam trap

A common misconception is that a negative step reverses the start and stop indices, leading candidates to incorrectly assume the slice starts at the lower index and moves forward, or that the stop index is inclusive when the step is negative.

How to eliminate wrong answers

Option A is wrong because 'fh' would be the result if the slice started at index 5 and went forward with step 2 (e.g., s[5:7:2]), but here the step is -2 and the start is 7, so the order is reversed. Option C is wrong because 'h' would be the result if the slice were s[7:3:-1] and stopped after one step, but with step -2, two characters are included (indices 7 and 5). Option D is wrong because 'hfd' would require three characters from indices 7, 5, and 3, but index 3 is the exclusive stop and is not included, so only two characters are extracted.

130
MCQmedium

You are developing a Python application that processes financial transactions. The application is structured as a package named `finance`. Inside `finance`, there are subpackages: `models`, `services`, and `utils`. The `services` subpackage contains a module `validator.py` that defines a function `validate_transaction()`. This function uses a helper function `check_amount()` defined in `utils.helpers`. The package is used by multiple other projects, and you want to ensure that importing `finance` does not accidentally expose internal helper functions. You also want to allow users to easily import the main validation function via `from finance import validate_transaction`. Which of the following approaches best achieves these goals?

A.In `finance/__init__.py`, write `from . import services` and `from .services import validator`. Then users can call `finance.services.validator.validate_transaction()`.
B.In `finance/__init__.py`, write `from .services.validator import validate_transaction`. Then users can call `finance.validate_transaction()`.
C.In `finance/__init__.py`, write `from .services import validator`. Then users can call `finance.validator.validate_transaction()`.
D.In `finance/__init__.py`, write `from .utils.helpers import *` and `from .services.validator import validate_transaction`.
AnswerB

Importing `validate_transaction` directly from its defining submodule and binding it in `finance/__init__.py` creates a single, callable attribute `finance.validate_transaction`. This is the recommended re-export pattern for exposing a clean public API: users get a flat namespace while the implementation remains organized under submodules. The function's original module is unchanged, but the package-level binding gives the desired shortcut.

Why this answer

It imports the `validate_transaction` function directly into the `finance` package namespace via `from .services.validator import validate_transaction` in `finance/__init__.py`. This allows users to use `from finance import validate_transaction` as desired, while keeping internal helper functions like `check_amount` in `utils.helpers` unexposed, since they are not imported into the package's top-level namespace. This approach follows the principle of explicit imports and encapsulation.

Exam trap

Python Institute often tests the distinction between importing a module versus importing a specific name from a module, and the trap here is that candidates may think importing the module (e.g., `from .services import validator`) is sufficient to allow `from finance import validate_transaction`, when in fact it only makes `finance.validator` available, not the function directly.

How to eliminate wrong answers

Option A is wrong because it only imports the `services` subpackage and the `validator` module, requiring users to call `finance.services.validator.validate_transaction()`, which does not satisfy the requirement of importing via `from finance import validate_transaction`. Option C is wrong because it imports the `validator` module into the `finance` namespace, so users would call `finance.validator.validate_transaction()` instead of `finance.validate_transaction()`, failing the desired import pattern. Option D is wrong because it uses `from .utils.helpers import *`, which exposes all names from `helpers` (including the internal `check_amount`) into the `finance` namespace, violating the goal of not accidentally exposing internal helper functions.

131
MCQhard

A script runs: import sys; print(sys.path[0]). The output is an empty string. What does this indicate?

A.The script is being read from stdin.
B.Python was launched with the -I flag.
C.The current working directory is not in sys.path.
D.The script is running from an interactive shell.
AnswerA

When Python executes a script from standard input (for example, via `python < script.py`), there is no script directory to place at the front of `sys.path`. In that situation, CPython sets `sys.path[0]` to the empty string `''`, which the import system interprets as "search the current working directory." Because `print(sys.path[0])` prints that empty string, the output is a blank line, and the value itself is the documented signal that the script came from stdin. This is a deliberate design decision so that modules in the current directory remain importable even when no script file path exists.

Why this answer

When a script is read from stdin (e.g., via `python < script.py` or `echo 'print(1)' | python`), Python sets `sys.path[0]` to an empty string because there is no script file path to derive the directory from. This is the documented behavior: `sys.path[0]` is the directory containing the script, or an empty string if the script is read from standard input.

Exam trap

Python Institute often tests the subtle distinction between `sys.path[0]` being empty (stdin/`-c`) versus being the script's directory (file execution), and candidates confuse this with the current working directory or the `-I` flag's effect on `sys.path`.

How to eliminate wrong answers

Option B is wrong because the `-I` flag (isolated mode) prevents `sys.path` from including the script's directory or the user site-packages, but it does not cause `sys.path[0]` to be an empty string; it would still contain the script's directory if a script file is given. Option C is wrong because the current working directory is not in `sys.path` by default in Python 3 (it was in Python 2), but `sys.path[0]` specifically refers to the script's directory, not the CWD. Option D is wrong because when running from an interactive shell, `sys.path[0]` is set to the directory of the script that started the interpreter (or an empty string if no script), but the interactive shell itself does not cause an empty string; the empty string only occurs when the script is read from stdin.

132
MCQhard

Which of these is NOT a characteristic of Python's descriptor protocol?

A.A descriptor can be used to create properties with custom behavior
B.Descriptors are only used for attributes that are read-only
C.Class variables assigned to a descriptor are automatically intercepted
D.A descriptor must implement __get__
AnswerB

Descriptors can also handle writes and deletes.

Why this answer

Descriptors are not limited to read-only attributes; they can control get, set, and delete operations. A descriptor that only implements `__get__` is a non-data descriptor, which can be overridden by instance attributes, while a data descriptor implements both `__get__` and `__set__` (and optionally `__delete__`), allowing full read-write control. The statement that descriptors are only for read-only attributes is false, as they are commonly used for computed properties, validation, and lazy evaluation.

Exam trap

Python Institute often tests the misconception that descriptors are only for read-only attributes, but the trap here is that descriptors can be read-write (data descriptors) or read-only (non-data descriptors), and the protocol requires at least `__get__`, not that attributes are immutable.

How to eliminate wrong answers

Option A is wrong because descriptors can indeed be used to create properties with custom behavior, such as validation or computed values, via the `__get__`, `__set__`, and `__delete__` methods. Option C is wrong because class variables assigned to a descriptor are automatically intercepted when accessed on an instance, due to Python's attribute lookup precedence (data descriptors override instance attributes). Option D is wrong because a descriptor must implement `__get__` to be considered a descriptor at all; the protocol requires at least `__get__`, while `__set__` and `__delete__` are optional.

133
MCQmedium

A team uses virtual environments to manage dependencies. They need to ensure that a script runs with the exact same module versions across different environments. Which approach is best?

A.Use sys.path.append to add module directories.
B.Copy the entire virtual environment folder to other systems.
C.Include the modules in a __pycache__ directory.
D.Run pip freeze and store the output in a requirements.txt file, then use pip install -r on other systems.
AnswerD

This is the standard method for replicating environments.

Why this answer

`pip freeze` outputs the exact versions of all installed packages in the current environment, and storing that output in a `requirements.txt` file allows you to reproduce the same environment on another system by running `pip install -r requirements.txt`. This ensures deterministic dependency management across different environments, which is the standard practice for reproducible builds in Python.

Exam trap

Python Institute often tests the misconception that copying the virtual environment folder (Option B) is a valid way to replicate dependencies, but the trap is that virtual environments are not portable across different operating systems or Python versions due to absolute paths and compiled extensions.

How to eliminate wrong answers

Option A is wrong because `sys.path.append` only adds directories to Python's module search path at runtime; it does not control which versions of modules are installed, nor does it ensure the same versions across environments. Option B is wrong because copying the entire virtual environment folder is platform-dependent (e.g., paths and compiled binaries may not work on different OS or Python versions) and is not a portable or recommended practice. Option C is wrong because `__pycache__` directories contain bytecode cache files (`.pyc`) that are specific to the Python interpreter version and are not meant for distributing or managing module versions; they are automatically regenerated and do not include the original source or version metadata.

134
MCQmedium

A developer is writing a package that contains multiple modules. The package should allow users to import it directly and have all commonly used functions available at the package level. For example, after `import mypackage`, the user should be able to call `mypackage.func1()` without needing to import submodules. Which is the best way to achieve this?

A.Create a wrapper function in `__init__.py` that delegates calls to the submodule functions.
B.Include `__all__` in each submodule and ensure `__init__.py` is empty.
C.In `__init__.py`, import the desired functions from the submodules, e.g., `from .submodule import func1`.
D.Define a list named `__all__` in the package's `__init__.py` that lists the functions.
AnswerC

Importing the desired functions directly into `__init__.py` with relative imports, e.g. `from .submodule import func1`, binds those names in the package's namespace at import time. This is the canonical re-export pattern: after this line, `import package; package.func1` and `from package import func1` both succeed, while the submodule remains accessible as `package.submodule`. It gives the package a stable public API without duplicating logic.

Why this answer

`__init__.py` is executed when a package is imported, and importing functions from submodules into `__init__.py` makes them directly accessible as attributes of the package object. This allows `mypackage.func1()` to work without requiring the user to import submodules explicitly, satisfying the requirement of a flat namespace at the package level.

Exam trap

Python Institute often tests the distinction between `__all__` (which controls `from package import *` behavior) and actual imports in `__init__.py` (which populate the package namespace), causing candidates to mistakenly believe that `__all__` alone makes functions accessible at the package level.

How to eliminate wrong answers

Option A is wrong because a wrapper function in `__init__.py` that delegates calls would require the user to call a function (e.g., `mypackage.func1()`) that internally dispatches to submodule functions, but this approach is unnecessarily complex and does not directly expose the submodule functions as package attributes; it also breaks direct attribute access and introspection. Option B is wrong because including `__all__` in each submodule controls what is exported when using `from submodule import *`, but an empty `__init__.py` does not import anything into the package namespace, so `mypackage.func1()` would fail with an AttributeError. Option D is wrong because defining `__all__` in `__init__.py` only controls what is exported when using `from mypackage import *`; it does not actually import the functions into the package namespace, so `mypackage.func1()` would still raise an AttributeError unless the functions are explicitly imported.

135
MCQhard

Refer to the exhibit. What is the output?

A.1 1
B.0 1
C.1 2
D.2 2
AnswerC

This is correct because the two values are read from different namespaces. Example.attr directly accesses the class attribute, which remains 1 after assignment. In contrast, e.attr = 2 creates an instance attribute named 'attr' that shadows the class attribute during attribute lookup on that instance, so the instance dump returns 2. Therefore the output is exactly 1 2.

Why this answer

'1 2'. When `print(A.x, a.x)` is executed, `A.x` accesses the class attribute `x=1`, and `a.x` accesses the instance attribute `x=2` (set in `__init__`), which shadows the class attribute for that instance. Therefore, the output is '1 2'.

Exam trap

The trap is that candidates may think `self.x = 2` modifies the class attribute for all instances, leading them to choose '2 2', or they may forget the instance attribute shadows the class attribute, choosing '1 1'.

How to eliminate wrong answers

Option A is wrong because '1 1' would only occur if both `a.x` and `A.x` accessed the class attribute, but the instance attribute `self.x = 2` shadows the class attribute for the instance. Option B is wrong because '0 1' would require `x` to be 0 somewhere, which is never assigned. Option D is wrong because '2 2' would require `A.x` to also be 2, but the class attribute `x` remains 1 and is not modified by the instance assignment.

136
Multi-Selecthard

Which THREE of the following statements about Python packages and modules are true?

Select 3 answers
A.The sys.path list is read-only and cannot be modified at runtime.
B.A package must contain an __init__.py file to be importable.
C.A module is a single .py file containing Python definitions and statements.
D.The __all__ variable defines the public API of a module or package.
E.Relative imports use dots to refer to the current and parent packages.
AnswersC, D, E

This is the definition of a module.

Why this answer

A module in Python is defined as a single .py file that contains Python definitions, such as functions, classes, and variables, as well executable statements. This is the fundamental unit of code organization in Python, and any .py file can be imported as a module.

Exam trap

Python Institute often tests the misconception that sys.path is immutable or that __init__.py is always mandatory, leading candidates to incorrectly mark A or B as true when they are false under current Python behavior.

137
MCQmedium

A Python class 'BankAccount' has a method 'withdraw(amount)' that deducts 'amount' from 'self.balance'. A developer writes a subclass 'SavingsAccount' that overrides 'withdraw' to add a penalty if balance drops below minimum. Which design pattern is being used?

A.Composition
B.Aggregation
C.Method overriding
D.Inheritance
AnswerC

The subclass provides a specific implementation of the inherited method.

Why this answer

Method overriding is the mechanism where a subclass provides a specific implementation of a method that is already defined in its superclass. In this scenario, SavingsAccount overrides the withdraw method from BankAccount to add penalty logic, which is the defining characteristic of method overriding in Python.

Exam trap

The trap here is that candidates often confuse inheritance (the relationship) with method overriding (the specific technique), leading them to select 'Inheritance' instead of 'Method overriding' when the question explicitly describes a subclass redefining a parent method.

How to eliminate wrong answers

Option A is wrong because composition is a design pattern where a class contains instances of other classes as members to achieve code reuse, not where a subclass redefines a parent method. Option B is wrong because aggregation is a special form of composition representing a 'has-a' relationship with a weaker ownership lifecycle, not the act of overriding a method. Option D is wrong because inheritance is the broader mechanism that allows SavingsAccount to derive from BankAccount, but the specific pattern described—redefining withdraw in the subclass—is method overriding, not inheritance itself.

138
MCQhard

A developer needs to extract the file extension from a filename like 'document.pdf'. Which expression returns 'pdf'?

A.filename.split('.')[1]
B.filename.split('.')[0]
C.filename.rsplit('.', 1)[-1]
D.filename[-3:]
AnswerC

Splits from right at the last dot, returning the extension correctly.

Why this answer

`rsplit('.', 1)[-1]` splits the string from the right at the last occurrence of the dot, limiting to one split, and then retrieves the last element (index -1), which is the file extension. This handles filenames with multiple dots (e.g., 'archive.tar.gz') correctly, returning only the final extension.

Exam trap

The PCAP exam often tests the misconception that `split('.')[1]` is safe for extracting extensions, but the trap is that it fails for filenames with multiple dots or no dot, whereas `rsplit` with maxsplit handles these edge cases correctly.

How to eliminate wrong answers

Option A is wrong because `split('.')[1]` will fail with an IndexError if the filename has no dot, and for filenames with multiple dots it returns the second part (e.g., 'tar' from 'archive.tar.gz'), not the final extension. Option B is wrong because `split('.')[0]` returns the part before the first dot (e.g., 'document'), never the extension. Option D is wrong because `filename[-3:]` assumes the extension is exactly three characters, which fails for extensions like '.html' (returns 'tml') or '.py' (returns '.py' but only works by coincidence for three-letter extensions).

139
MCQeasy

What is the result of the expression '12345'[:10]?

A.'12345 '
B.'12345'
C.IndexError
D.'12345 '
AnswerB

The expression slices the string literal '12345' with a stop index that exceeds the string's length. Python's slice operation clamps out-of-range boundaries to the sequence's actual length, so it returns every character from index 0 through index 4. Thus the result is exactly the original five-character string '12345', with no error and no added whitespace.

Why this answer

In Python, slicing a string with a start index of 0 and an end index of 10 (as in '12345'[:10]) returns the entire string if the slice end exceeds the string length. Since '12345' has only 5 characters, the slice extracts all characters without padding or error, resulting in '12345'.

Exam trap

The PCAP exam often tests the misconception that slicing beyond the string length causes an IndexError or that Python automatically pads the result to the specified length, leading candidates to choose A or C instead of recognizing the graceful truncation.

How to eliminate wrong answers

Option A is wrong because it incorrectly assumes Python pads the slice with spaces to reach length 10, but slicing never adds padding—it only extracts existing characters. Option C is wrong because Python slicing does not raise an IndexError when the end index is beyond the string length; it simply returns the substring up to the actual length. Option D is wrong because it includes a trailing space, but slicing does not append any characters, even a single space.

140
MCQeasy

A company needs to model different types of employees. They have a base class `Employee` with a method `calculate_pay()`. For hourly employees, pay = hours * rate; for salaried employees, pay = salary. Which design approach is most appropriate?

A.Use a `@staticmethod` inside `Employee` to compute pay based on a type parameter.
B.Define a module-level function that takes an employee object and computes pay.
C.Create subclasses `HourlyEmployee` and `SalariedEmployee` that override `calculate_pay()`.
D.Use a single `Employee` class with conditional statements to differentiate pay types.
AnswerC

This uses inheritance and polymorphism, the standard OOP approach for such scenarios.

Why this answer

It applies polymorphism through method overriding: each subclass (`HourlyEmployee`, `SalariedEmployee`) provides its own implementation of `calculate_pay()`, allowing the calling code to treat all employees uniformly via the base class interface. This adheres to the Open/Closed Principle and keeps the design extensible without modifying existing code when new employee types are added.

Exam trap

Python Institute often tests the distinction between using inheritance with method overriding versus using conditionals or static methods, and the trap here is that candidates may think a single class with `if` statements is simpler and therefore better, missing the long-term maintenance and extensibility advantages of polymorphism.

How to eliminate wrong answers

Option A is wrong because a `@staticmethod` cannot access instance attributes (`hours`, `rate`, `salary`) without passing them explicitly, and using a type parameter violates polymorphism by requiring conditional logic inside the static method. Option B is wrong because a module-level function breaks encapsulation and does not leverage the class hierarchy, making it harder to extend and maintain as employee types grow. Option D is wrong because using conditional statements inside a single `Employee` class violates the Open/Closed Principle and leads to fragile code that must be modified every time a new pay type is introduced.

141
MCQhard

Refer to the exhibit. What is the output and why?

A.AttributeError
B.1
C.2
D.3
AnswerC

Correct. The class attribute `counter` starts at 0 and is incremented by 1 each time an instance is created. Two instances are created, so `A.counter` becomes 2.

Why this answer

The code defines a class `A` with a class attribute `counter` set to 0, and an `__init__` method that increments `A.counter` (the class attribute) by 1 each time an instance is created. Creating two instances (`a1` and `a2`) increments the class attribute twice, so `A.counter` becomes 2. The `print(A.counter)` statement outputs the class attribute value, which is 2.

Exam trap

The trap here is that candidates may mistakenly think `self.counter` is being incremented (creating an instance attribute) rather than `A.counter` (the class attribute), leading them to expect the output to be 1 or to overlook that the class attribute is shared and incremented by each instantiation.

How to eliminate wrong answers

Option A is wrong because there is no AttributeError; the class attribute `counter` is defined and accessed correctly via `A.counter`. Option B is wrong because the output is not 1; creating two instances increments the counter twice, not once. Option D is wrong because the output is not 3; only two instances are created, so the counter is incremented exactly twice, not three times.

142
MCQhard

A package 'mypackage' has subpackages 'sub1' and 'sub2'. In sub1/__init__.py, there is: from sub2 import helper. When importing mypackage, an ImportError occurs: No module named 'sub2'. What is the most likely cause?

A.Sub2 is not installed in the Python environment.
B.Sub2 must be imported before sub1 in the package's __init__.py.
C.Sub1 should not have an __init__.py file.
D.The import should be from .sub2 import helper (relative import).
AnswerD

Relative imports are required to locate sibling packages within a package.

Why this answer

When a subpackage (sub1) tries to import from a sibling subpackage (sub2) using a bare name (from sub2 import helper), Python looks for 'sub2' as a top-level module, not as a sibling within the same parent package. Since 'sub2' is not installed as a top-level module, an ImportError occurs. Using a relative import (from .sub2 import helper) explicitly tells Python to look for sub2 as a sibling package under the same parent, resolving the import correctly.

Exam trap

Python Institute often tests the distinction between absolute and relative imports in packages, trapping candidates who assume that sibling subpackages are automatically visible to each other without using dot-based relative imports.

How to eliminate wrong answers

Option A is wrong because the error 'No module named sub2' occurs even if sub2 is present in the package directory; the issue is the import path, not installation. Option B is wrong because the order of importing subpackages in the parent __init__.py does not affect how sub1 resolves its own imports; the error stems from sub1's internal import statement, not from the parent's import sequence. Option C is wrong because removing __init__.py from sub1 would prevent it from being recognized as a package, breaking all imports from it, not fixing the sibling import issue.

143
MCQeasy

A junior developer wrote a class representing a bank account with a private attribute balance. They used double underscore prefix (__balance) to make it private. However, in a test script, they are still able to access the attribute using the mangled name _Account__balance. The developer is confused about why encapsulation is not enforced. Which statement best explains this behavior?

A.The double underscore prefix actually makes the attribute completely inaccessible from outside the class.
B.Python's name mangling is only a convention and does not prevent access.
C.The developer forgot to use the @property decorator.
D.The test script must have used a different class attribute name.
AnswerB

Name mangling is a syntactic transformation, not a security mechanism: `self.__balance` inside a class becomes `self._BankAccount__balance`. It does not prevent external code from accessing the attribute via that mangled name, so it is only a convention. It primarily helps avoid accidental overrides in subclasses rather than hiding data.

Why this answer

Python's name mangling (triggered by a double underscore prefix) is not a security mechanism but a syntactic transformation that renames the attribute to _ClassName__attribute. This prevents accidental name clashes in subclasses but does not enforce true encapsulation; the attribute can still be accessed via the mangled name from outside the class. The developer's confusion stems from mistaking name mangling for a privacy guarantee, which Python intentionally does not provide.

Exam trap

The trap here is that Python Institute often tests the misconception that double underscore prefix enforces true privacy like in languages such as Java or C++, when in reality Python's name mangling is merely a renaming convention that does not prevent access from outside the class.

How to eliminate wrong answers

Option A is wrong because the double underscore prefix does not make the attribute completely inaccessible; it only triggers name mangling, and the attribute remains accessible via the mangled name (e.g., _Account__balance). Option C is wrong because the @property decorator is used to define getter/setter methods for controlled access, but its absence does not affect the ability to access the attribute directly via the mangled name; the core issue is about privacy enforcement, not property decorators. Option D is wrong because the test script correctly uses the mangled name _Account__balance, which is the actual attribute name after mangling; there is no different class attribute name involved.

144
Multi-Selecteasy

Which TWO of the following are valid ways to define a class attribute that is shared by all instances?

Select 2 answers
A.class MyClass: attr: int = 0
B.class MyClass: def set_attr(self): MyClass.attr = 0
C.class MyClass: pass MyClass.attr = 0
D.class MyClass: attr = 0
E.class MyClass: def __init__(self): self.attr = 0
AnswersC, D

Assigns a class attribute after definition.

Why this answer

Assigning an attribute directly to the class after its definition (MyClass.attr = 0) creates a class-level attribute that is shared by all instances. Option D is correct because defining an attribute directly inside the class body (attr = 0) also creates a class-level attribute, accessible to all instances unless shadowed by an instance attribute.

Exam trap

Python Institute often tests the distinction between class attributes and instance attributes, and the trap here is that candidates confuse type annotations (which do not create attributes) with actual assignments, or think that assigning inside a method (like __init__) creates a class-level attribute when it actually creates an instance attribute.

145
Multi-Selectmedium

Which TWO of the following are valid ways to import a module named 'math' and give it an alias 'm'?

Select 1 answer
A.from math import * as m
B.import math as m
C.import math m
D.import math alias m
E.from math import sin as m
AnswersB

Correct syntax: `import math as m` imports the full math module with alias m.

Why this answer

Only B. Option B uses the correct syntax `import math as m` to import the entire math module with alias m. Option A is invalid because the asterisk (*) cannot be combined with an alias in a `from ... import` statement.

Option C is missing the `as` keyword. Option D uses `alias` which is not a valid keyword; the correct keyword is `as`. Option E imports a specific function (sin) from math, not the module itself; therefore it does not satisfy the requirement to import the module and give it an alias.

Exam trap

Python Institute often tests the distinction between `import module as alias` and `from module import name as alias`, and the trap here is that candidates may confuse the alias syntax for modules with the alias syntax for specific names, or incorrectly assume that `alias` is a valid keyword.

146
MCQhard

A developer has two separate directories on sys.path: /home/user/libs and /opt/libs. Both directories contain a subdirectory 'mypackage' without an __init__.py file. The developer wants to import a module from 'mypackage' that exists only in one of the directories. What concept allows Python to treat these two directories as a single namespace package?

A.Regular packages with __init__.py
B.sys.path merging
C.Implicit namespace packages (PEP 420)
D.Package overriding
AnswerC

PEP 420 introduced implicit namespace packages, which allow a dotted package name to be composed from multiple separate directories on sys.path without requiring __init__.py in any of them. When the import system encounters a directory named home that has no __init__.py, it records that directory as one portion of the package and continues scanning later sys.path entries for additional home directories, assigning the combined list of portions to __path__. This is exactly the mechanism that lets two physically separate directory trees collectively provide the submodules of the package home.

Why this answer

PEP 420 introduced implicit namespace packages, which allow multiple directories on sys.path to contribute to the same package without requiring __init__.py files. When Python encounters a directory without __init__.py, it treats it as a namespace package, merging all matching directories across sys.path into a single logical package. This enables the developer to import a module from 'mypackage' that exists in only one of the directories, as Python searches all paths and resolves the module from the first location where it is found.

Exam trap

Python Institute often tests the distinction between regular packages (with __init__.py) and implicit namespace packages (without __init__.py), and the trap here is that candidates mistakenly think sys.path merging or package overriding is the correct concept, when in fact PEP 420's implicit namespace packages are the precise mechanism that allows multiple directories to form a single package without __init__.py.

How to eliminate wrong answers

Option A is wrong because regular packages require an __init__.py file to be present, which is explicitly stated as missing in the question; using regular packages would not allow the two directories to be treated as a single package. Option B is wrong because sys.path merging is not a Python concept; sys.path is a list of directories that Python searches sequentially, but it does not merge directories into a single namespace package. Option D is wrong because package overriding is not a standard Python mechanism; Python does not override packages but instead uses the first module found on sys.path, and without __init__.py, it relies on namespace packages to combine directories.

147
MCQhard

Consider the following code: print('"age": 30,')

A."age": 30
B."age": 30,
C."name": "Alice",
D."city": "New York"
AnswerB

This is the exact third line of the pretty-printed JSON output when `indent=2` is used. The line begins with two spaces (the indentation for properties at the top level), then the key `"age"`, a colon and a space, and the value `30`, followed by a trailing comma. That comma is required because the `"city"` property still follows; this line matches the code's actual output verbatim.

Why this answer

The code prints a literal string: "age": 30,. The double quotes are escaped within the single-quoted string, so they appear in the output. The trailing comma is part of the string, not a delimiter.

Exam trap

This question tests attention to detail: the string includes a trailing comma, which is easy to overlook if the candidate assumes it's a dictionary serialization.

How to eliminate wrong answers

Option A is wrong because it omits the trailing comma that appears in the output when multiple key-value pairs are present in the dictionary or JSON string. Option C is wrong because it shows only the "name" key-value pair, but the output includes the "age" key-value pair as well, indicating the code prints more than just that. Option D is wrong because it shows "city": "New York", which is not part of the given output; the code likely does not include that key-value pair in the printed data.

148
Multi-Selecteasy

Which TWO of the following file modes will create a new file if it doesn't exist? (Select exactly 2)

Select 2 answers
A.'x'
B.'a'
C.'rb'
D.'w'
E.'r'
AnswersA, B

Fails if file exists.

Why this answer

('x') is correct because exclusive creation mode creates a new file and fails if it already exists. Option B ('a') is correct because append mode creates a new file if it does not exist, allowing data to be added at the end. Option D ('w') also creates a file if missing, but it truncates existing content, which may cause data loss; however, the question requires exactly two correct answers, and the non-destructive creation modes are 'x' and 'a'.

Exam trap

Candidates often confuse 'x' with 'r' or think that 'x' does not create a file. In fact, 'x' and 'a' both create a file if it does not exist, while 'w' also creates but truncates.

149
MCQmedium

You maintain a Python library 'myutils' that is installed as a package in the system. The library has a submodule 'config' that reads configuration from a file. Recently, a user reported that after updating the library, their application still uses the old configuration values. They confirmed that the config file on disk has been updated. The library's __init__.py does: from .config import load_config. The user's application imports load_config from myutils and calls it each time they need configuration. What is the most likely cause of the issue?

A.The user did not restart the Python interpreter, so sys.modules still contains the old module.
B.The import statement in __init__.py is cached, so the module is not reloaded even after update.
C.The library's .pyc files were not regenerated because the .py timestamps were not updated during the install, so Python used the cached bytecode from the previous version.
D.The config module caches the configuration file contents in memory after the first read.
AnswerC

Python's import machinery validates cached bytecode by comparing the source file's modification time (and often size) with the values stored in the .pyc header. If an installer copies only the .py files without updating their mtimes—for example, by preserving timestamps from the build or using a tool that does not touch the destination files—the old .pyc still appears to match the unchanged source timestamp. Python then loads the stale bytecode instead of recompiling, so even though the .py file on disk contains the new code, the interpreter executes the previous version.

Why this answer

Python caches compiled bytecode in .pyc files. If the .pyc file's timestamp is newer than the corresponding .py file, Python will use the cached bytecode without recompiling. During a package update, if the .py files' timestamps are not updated (e.g., due to a flawed installation process), Python continues to load the old .pyc, causing the old configuration-reading code to execute even though the config file on disk has changed.

Exam trap

Python Institute often tests the misconception that Python always recompiles .pyc files when the source changes, but the trap is that Python relies on file timestamps, not content hashes, so a stale .pyc can persist if the .py timestamp is not updated during installation.

How to eliminate wrong answers

Option A is wrong because the user is calling load_config each time they need configuration, not relying on a module-level cached value; restarting the interpreter would not fix stale bytecode if the .pyc is still newer than the .py. Option B is wrong because the import statement in __init__.py is not cached; Python's import system caches the loaded module object in sys.modules, but the user is importing load_config and calling it repeatedly, so the module is already loaded and the function is executed fresh each call. Option D is wrong because the question states the user confirmed the config file on disk has been updated, and the issue is that the library code itself is stale (not that the config module caches file contents in memory).

150
MCQmedium

A programmer wants to create a class that cannot be instantiated directly, only through a factory method. Which approach should be used?

A.Raise an exception in __init__ if called directly.
B.Define the class as abstract using ABC and @abstractmethod.
C.Override __new__ to raise an exception unless called from a classmethod factory.
D.Use a metaclass to prevent instantiation.
AnswerC

As the actual instance-creation hook, __new__ runs before __init__; raising an exception there prevents the instance from ever coming into existence. A classmethod factory can be written to call cls.__new__(cls) while suppressing the guard (e.g., through a private flag), enabling controlled creation. This pattern is the standard way to enforce a factory-only or singleton design, because direct calls to Class() are intercepted at the earliest point.

Why this answer

Overriding `__new__` allows the programmer to control instance creation at the lowest level. By checking the call stack or a flag set by a classmethod factory, `__new__` can raise an exception when instantiation is attempted directly, while still allowing the factory method to create instances. This ensures the class cannot be instantiated directly, only through the designated factory.

Exam trap

Python Institute often tests the distinction between `__new__` and `__init__`, and the trap here is that candidates think raising an exception in `__init__` (Option A) is sufficient, not realizing that `__new__` has already created the object and the exception only prevents full initialization, not allocation.

How to eliminate wrong answers

Option A is wrong because raising an exception in `__init__` still allows the object to be partially created (memory allocated by `__new__`), and the exception can be caught, leaving a half-initialized object or causing confusion; it does not prevent instantiation at the allocation stage. Option B is wrong because defining a class as abstract with ABC and @abstractmethod prevents instantiation only if the class has unimplemented abstract methods; if all abstract methods are implemented, the class can be instantiated directly, which does not enforce the factory-only requirement. Option D is wrong because using a metaclass to prevent instantiation is overly complex and not a standard Python pattern for this specific need; it would require overriding `__call__` in the metaclass, which is less direct and more error-prone than overriding `__new__` in the class itself.

Page 1

Page 2 of 3

Page 3

All pages