Courseiva

Certified Associate Python Programmer PCAP (PCAP) — Questions 151–225

421 questions total · 6pages · All types, answers revealed

Page 2

Page 3 of 6

Page 4
151
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.

152
MCQeasy

A data entry application reads a CSV file where each line contains fields separated by commas. However, some fields are enclosed in double quotes and contain commas inside, e.g., 'John,"Doe, Jr.",30'. The developer currently uses line.split(',') to parse each line, which incorrectly splits the quoted field. The developer wants a solution using only the Python standard library (no third-party packages). Which of the following is the best approach?

A.Use the csv module's reader: import csv; next(csv.reader([line]))
B.Use line.strip().split(',') and then manually merge fields that start with a quote
C.Iterate through each character, track whether inside quotes, and split on commas outside quotes
D.Write a regular expression that matches commas outside quotes
AnswerA

The csv module implements RFC 4180 quoting rules, so its reader correctly treats commas inside double-quoted fields as literal data rather than delimiters. Passing the single line in a list yields the parsed fields, and csv ships with the standard library.

Why this answer

The csv module's reader is specifically designed to handle CSV parsing according to RFC 4180, including quoted fields with embedded commas. By passing the line wrapped in a list to csv.reader, the developer gets a properly parsed list of fields without needing to manually handle quote escaping or comma splitting.

Exam trap

The PCAP exam often tests the candidate's knowledge of the standard library's csv module as the idiomatic and correct way to parse CSV data, expecting candidates to recognize that manual string splitting or regex approaches are fragile and not recommended for production code.

How to eliminate wrong answers

Option B is wrong because manually merging fields that start with a quote is error-prone and does not handle edge cases like escaped quotes ("") or fields that contain quotes but do not start with them. Option C is wrong because while character-by-character parsing can work, it is unnecessarily complex, error-prone, and reinvents the wheel when the csv module already provides a robust, tested implementation. Option D is wrong because writing a regular expression to match commas outside quotes is notoriously difficult to get right, especially with nested quotes or escaped quotes, and the csv module avoids this complexity entirely.

153
MCQeasy

A class `Point` has an `__init__` that sets `self.x` and `self.y`. They want to compare points by equality (i.e., `p1 == p2` should work correctly). Which method should they implement?

A.`__same__`
B.`__eq__`
C.`__compare__`
D.`__cmp__`
AnswerB

`__eq__` is the correct special method to override for the equality operator (`==`) in Python. By implementing `__eq__` in the `Point` class, you can compare two point instances based on their coordinate attributes (e.g., `self.x == other.x and self.y == other.y`) rather than by their identity. This is the standard, documented approach for value equality in Python's object model.

Why this answer

In Python, the `__eq__` method is the correct way to define equality comparison for objects. When you implement `__eq__(self, other)`, it is automatically called by the `==` operator, allowing `p1 == p2` to return a Boolean based on custom logic (e.g., comparing `self.x` and `self.y`). This is the standard Python protocol for equality testing.

Exam trap

Python Institute often tests the distinction between Python 2's `__cmp__` and Python 3's `__eq__`; the trap here is that candidates familiar with older Python may incorrectly choose `__cmp__`, not realizing it is obsolete in Python 3.

How to eliminate wrong answers

Option A is wrong because `__same__` is not a Python special method; Python uses `__eq__` for equality, not `__same__`. Option C is wrong because `__compare__` is not a Python dunder method; Python uses `__eq__` for equality and `__lt__`, `__gt__`, etc. for ordering. Option D is wrong because `__cmp__` was used in Python 2 for comparison (returning -1, 0, 1) but was removed in Python 3; the PCAP exam focuses on Python 3, where `__eq__` is the correct method for equality.

154
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

Decorating `make_sound` with `@abstractmethod` inside a class inheriting from `ABC` registers it as abstract, so Python raises `TypeError` when any subclass omits the override or when `Animal` itself is instantiated. This directly enforces the stem's requirement that every subclass implement `make_sound`.

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.

155
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

Python's find() returns the lowest index of the substring within the string, or -1 when absent, which is exactly the specified behaviour. index() raises ValueError instead of returning -1, and count() or search() do not return positional indices.

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.

156
MCQhard

A programmer is writing a script to generate SQL queries safely. They need to escape single quotes in user-provided strings to prevent injection. Which approach is most robust?

A.s.replace("\\'", "'")
B.s.replace("'", "\\'")
C.s.strip("'")
D.s.replace("'", "''")
AnswerD

This doubles every single quote, which is the standard SQL way to include a literal quote inside a string: the DBMS sees '' as an escaped quote and does not treat the second quote as the end of the literal. By replacing all occurrences of ' with '', every potentially dangerous quote is neutralized, preventing break-out SQL injection when building queries from unsanitized input.

Why this answer

In SQL, single quotes are escaped by doubling them (''), not by using backslashes. This is the standard escape mechanism defined by the SQL standard (ISO/IEC 9075) and is supported by databases like PostgreSQL, SQLite, and Oracle. Using `s.replace("'", "''")` ensures that a single quote in user input becomes two single quotes in the SQL string, preventing injection while preserving the literal quote.

Exam trap

Python Institute often tests the misconception that backslash escaping is universal in SQL, leading candidates to choose Option B, but the PCAP exam expects knowledge of the standard SQL escape mechanism (doubling quotes) as the most robust method.

How to eliminate wrong answers

Option A is wrong because it replaces the backslash-quote sequence with a single quote, which does not escape anything and actually removes the escape character. Option B is wrong because it uses a backslash to escape the quote, which is not the standard SQL escape method and may not work in all databases (e.g., MySQL with NO_BACKSLASH_ESCAPES mode disables it). Option C is wrong because `strip("'")` only removes leading and trailing single quotes, leaving internal quotes unescaped and vulnerable to injection.

157
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

`__init__` is a special (dunder) method automatically invoked by Python when an instance is created, initialising the object's attributes. It satisfies the stem's requirement for special methods, which are defined by reserved double-underscore names and called implicitly by the interpreter rather than by explicit invocation.

Why this answer

In Python, special methods (also called dunder or magic methods) are predefined methods with names of the form __name__ that the interpreter invokes implicitly to implement language features. Option C, `__init__`, is the initializer special method that Python calls automatically when an instance is created, e.g., `obj = MyClass()`, to set up the object's initial state. Option D, `__str__`, is the special method that Python calls by default by `str(obj)` and `print(obj)` to produce a human-readable string representation of the object.

By contrast, options A (`__bar__`) and E (`__foo__`) merely follow the double-underscore naming pattern but are not defined by the Python data model as special methods, so they are ordinary attributes. Option B, `__main__`, is not a method at all; it is the name of the top-level execution scope (the value of `__name__` for the main script) and the conventional module name checked with `if __name__ == "__main__":`.

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.

158
MCQmedium

Refer to the exhibit. A developer runs 'pip install pandas==2.0.0' but gets an error stating that the required version is not available. Which command should be used to list all available versions of pandas?

A.pip index versions pandas
B.pip search pandas
C.pip show pandas
D.pip list --all pandas
AnswerA

pip index versions pandas is correct because it contacts the configured package index (PyPI by default) and fetches the release history for the pandas project, listing every available version in ascending order. This is the only option that actually asks the remote index about versions, and it is the pip-native way to check which releases exist before installing or pinning one. Note that this subcommand is experimental, but it is still the right choice among the four.

Why this answer

`pip index versions pandas` is the command that queries the Python Package Index (PyPI) for all available versions of the specified package. This command was introduced in pip 21.1 and is the proper way to list version history without attempting to install.

Exam trap

Python Institute often tests the distinction between commands that query the remote index (`pip index`) versus commands that inspect the local environment (`pip show`, `pip list`), and candidates frequently confuse `pip search` (which searches package names) with listing versions.

How to eliminate wrong answers

Option B is wrong because `pip search pandas` is a deprecated command that searches for packages by name or description in PyPI, not for listing available versions of a specific package; it was removed in pip 23.0 due to XMLRPC API issues. Option C is wrong because `pip show pandas` displays metadata for an already installed package (version, location, dependencies), not available versions from the remote index. Option D is wrong because `pip list --all pandas` is not a valid pip syntax; `pip list` lists installed packages, and `--all` shows outdated packages, but it cannot filter by a specific package name in that way.

159
MCQmedium

Given s = 'Python', what is s[1:4]?

A.'pyt'
B.'yth'
C.'ytho'
D.'Pyt'
AnswerB

For s = 'Python', s[1:4] returns 'yth' because Python string indices are zero-based and slice end points are exclusive. The characters are P(0), y(1), t(2), h(3), o(4), n(5), so the slice takes positions 1, 2, and 3. Those positions spell 'y', 't', 'h' in order, giving exactly 'yth', which is the correct answer.

Why this answer

In Python, string slicing with `s[start:stop]` extracts characters from index `start` up to but not including index `stop`. Since indexing starts at 0, `s[1:4]` on 'Python' takes indices 1 ('y'), 2 ('t'), and 3 ('h'), resulting in 'yth'. Option B is correct because it exactly matches this slice.

Exam trap

Python Institute often tests the half-open interval behavior of slicing, where candidates mistakenly include the character at the stop index (e.g., choosing 'ytho' by including index 4) or confuse zero-based indexing with one-based indexing (e.g., choosing 'pyt' or 'Pyt' by starting at index 0).

How to eliminate wrong answers

Option A is wrong because 'pyt' would result from `s[0:3]` (lowercase 'p' at index 0, 'y' at 1, 't' at 2), not from `s[1:4]`. Option C is wrong because 'ytho' would require `s[1:5]` (including index 4 which is 'o'), exceeding the stop index of 4. Option D is wrong because 'Pyt' would result from `s[0:3]` (uppercase 'P' at index 0, 'y' at 1, 't' at 2), not from `s[1:4]` which starts at index 1.

160
MCQmedium

A developer is writing a script that processes user-uploaded CSV files. The script should attempt to read the file, and if a UnicodeDecodeError occurs, log a warning and skip the file. Which code snippet correctly achieves this without stopping the entire process?

A.try: read_file() except (UnicodeDecodeError, OSError): pass
B.try: read_file() except UnicodeDecodeError: log.warning('Skipping file')
C.try: read_file() except Exception: log.warning('Skipping file')
D.try: read_file() except UnicodeEncodeError: log.warning('Skipping file')
AnswerB

This is the correct approach because it deliberately catches only UnicodeDecodeError, which is the exception raised when reading and decoding bytes containing invalid UTF-8 or another specified codec. By logging a warning and doing nothing else, the handler reports the problem while allowing the surrounding loop to move on to the next uploaded file. More specific handlers like this leave unrelated exceptions—such as OSError or file-system errors—free to propagate, preserving their diagnostic value.

Why this answer

It catches only UnicodeDecodeError, which is the specific exception raised when a file contains invalid UTF-8 or other encoding issues. It logs a warning and then continues execution (the 'pass' is implied by the log statement, but the key is that the exception is handled without re-raising). This matches the requirement to skip the file without stopping the entire process.

Exam trap

Python Institute often tests the distinction between UnicodeDecodeError (input decoding) and UnicodeEncodeError (output encoding), and the trap here is that candidates confuse the two or use an overly broad except clause that hides bugs.

How to eliminate wrong answers

Option A is wrong because it catches both UnicodeDecodeError and OSError, but uses 'pass' instead of logging a warning, which fails the requirement to log a warning. Option C is wrong because it catches the broad Exception class, which would suppress all exceptions (including critical ones like KeyboardInterrupt or SystemExit) and violates best practices by being too broad. Option D is wrong because it catches UnicodeEncodeError, which is raised when encoding output (e.g., writing to a file), not when reading/decoding input; the correct exception for reading is UnicodeDecodeError.

161
MCQmedium

A developer writes a log message with variables: name = 'Alice' and age = 30. Which of the following uses an f-string correctly?

A.f(Name: {name}, Age: {age})
B.f'Name: {name}, Age: {age}'
C.'Name: %s, Age: %d' % (name, age)
D.f.'Name: {name}, Age: {age}'
AnswerB

This is a correctly formed f-string: the f prefix is directly attached to a single-quoted string literal, and each pair of curly braces contains an expression to be evaluated at runtime. Python inserts the values of the variables 'name' and 'age' into the string, converting them with their __format__ methods. The single quotes wrap the entire literal, making the syntax valid per PEP 498.

Why this answer

It uses the proper f-string syntax: the letter 'f' immediately followed by a string literal (single or double quotes) containing expressions in curly braces. In Python, f-strings (formatted string literals) evaluate expressions inside {} and insert them into the string at runtime, making them concise and readable.

Exam trap

The PCAP exam often tests the exact syntax of f-strings, specifically that the 'f' prefix must be immediately followed by a string literal (no space, no dot, no parentheses), and that the expressions inside curly braces are evaluated in the current scope.

How to eliminate wrong answers

Option A is wrong because the f-string prefix is missing the quotation marks — it uses parentheses instead of quotes, which is invalid syntax. Option C is wrong because it uses the old-style % formatting, not an f-string; while it works, it does not satisfy the requirement of using an f-string. Option D is wrong because it places a period between 'f' and the opening quote ('f.'), which is not valid Python syntax for an f-string.

162
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

In Python, 'raise TypeError(...) from None' explicitly suppresses the exception context, so the traceback shows only the TypeError and hides the original ValueError that triggered it. This is used when the original exception is irrelevant or confusing to the caller. Without 'from None', Python would chain the exceptions and display both.

Exam trap

The trap is assuming 'from None' means 'no chaining information at all' or that it re-raises the original — candidates must know it suppresses the display of the chained exception while still raising the new one, and that it is valid syntax.

How to eliminate wrong answers

Option A is wrong because 'from None' does not re-raise the original ValueError; it suppresses it from the displayed traceback, and the raised exception is the TypeError. Option B is wrong because 'raise ... from None' is valid Python 3 syntax (introduced in PEP 3134) and does not cause a syntax error. Option D is wrong because chaining the TypeError to the original ValueError is what happens by default or with 'from exc'; 'from None' does the opposite by suppressing the chain.

163
MCQmedium

A production script opens a configuration file with `open('config.ini', 'r')`. During a recent maintenance window, the file was replaced by a directory of the same name. The script now terminates with `IsADirectoryError`. The developer wants to catch this specific condition separately from a missing file and log a distinct message. Which `except` clause should be added?

A.except FileNotFoundError as e:
B.except IOError as e:
C.except OSError as e:
D.except IsADirectoryError as e:
AnswerD

IsADirectoryError is raised when the operating system reports that a path expected to be a regular file is actually a directory. Catching it by name lets the script log a specific message for that condition while allowing FileNotFoundError to fall through to its own handler. This directly satisfies the requirement to distinguish the two failures.

Why this answer

The directory-replacement scenario produces IsADirectoryError, a specific subclass of OSError raised when a path that should be a regular file resolves to a directory. Naming that exception in its own except clause isolates the condition and permits a tailored log message, while a separate FileNotFoundError clause can still handle a genuinely missing path. Broad parent handlers would merge the two cases.

Exam trap

The trap here is assuming that any file-access problem surfaces as FileNotFoundError or the generic OSError alias IOError, when a path that exists as a directory raises the distinct IsADirectoryError subclass.

164
MCQeasy

Consider the following code: name = "Alice" age = 30 print(f"{name} is {age} years old.") What is the output of the above code?

A.Alice is 30, years old.
B.Name is 30 years old.
C.Alice is 30 years old..
D.Alice is 30 years old.
AnswerD

In an f-string, expressions inside braces are evaluated and replaced with their string representation, so {name} becomes 'Alice' and {age} becomes '30'. The surrounding literal text ' is ' and ' years old.' is preserved verbatim, giving the exact concatenation 'Alice is 30 years old.'. This matches the expected output because the variable `name` holds the string 'Alice', and the integer `age` is 30.

Why this answer

Given the code:

name = "Alice"

age = 30

print(f"{name} is {age} years old.")

The f-string correctly interpolates the variables, producing 'Alice is 30 years old.' Option D is correct. Option A incorrectly includes an extra comma after 30. Option B uses the literal string 'Name' instead of the variable name. Option C adds an extra period at the end.

Exam trap

Python Institute often tests whether candidates notice subtle punctuation differences (like missing commas or extra periods) in f-string output, tricking those who focus only on the variable values and ignore exact string formatting.

How to eliminate wrong answers

Option A is wrong because it adds a comma after '30' and an extra space before 'years', which is not present in the f-string. Option B is wrong because it replaces the actual name with the literal string 'Name', showing a misunderstanding that f-string placeholders are evaluated, not left as variable names. Option C is wrong because it has two periods at the end (a double dot), while the f-string produces only one period.

165
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

The MRO for D is D, B, C, A, so `super()` inside B resolves to C, not A. B's `super().method()` therefore invokes C's method, which prints 'C' after its own `super()` call reaches A and prints 'A'. Control then returns to B, printing 'B', yielding A C B.

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).

166
Multi-Selectmedium

Which TWO of the following string methods return a boolean value (True or False)?

Select 2 answers
A.str.upper()
B.str.split()
C.str.startswith()
D.str.isdigit()
E.str.find()
AnswersC, D

str.startswith() is a predicate method: it evaluates the string against a condition and returns the boolean value True if the string begins with the given prefix, otherwise False. It also accepts optional start and end index arguments to scope the check, and can take a tuple of prefixes to test multiple alternatives at once. Because its entire purpose is to answer a Yes/No question about string content, it is one of the methods that truly returns a bool.

Why this answer

Both `str.startswith()` and `str.isdigit()` return a boolean value (`True` or `False`) because they are designed for conditional checks. `str.startswith()` checks if the string starts with a given prefix, while `str.isdigit()` checks if all characters in the string are digits. In contrast, `str.upper()` returns a new string, `str.split()` returns a list, and `str.find()` returns an integer index. Therefore, options C and D are the correct answers.

Exam trap

Python Institute often tests the distinction between methods that return a boolean versus those that return a new string or an integer, trapping candidates who confuse `str.find()` (returns index) with `str.startswith()` (returns boolean).

167
Multi-Selecteasy

Which TWO string methods raise an exception when the searched substring is not found?

Select 2 answers
A.rfind()
B.find()
C.rindex()
D.count()
E.index()
AnswersC, E

rindex() performs a right-to-left search but still returns the index of the match as measured from the left end of the original string. If the substring is not present, rindex() raises a ValueError, which is exactly the exception behavior that makes it a correct answer. It mirrors index() in its error semantics, differing only in the search direction.

Why this answer

(rindex()) is correct because the rindex() method, like index(), raises a ValueError exception when the searched substring is not found. This is in contrast to rfind() and find(), which return -1 instead of raising an exception.

Exam trap

Python Institute often tests the distinction between methods that return -1 (find, rfind) versus those that raise an exception (index, rindex), and the trap is that candidates confuse rfind() with rindex() because both perform a right-to-left search.

168
Multi-Selecthard

Which TWO statements about Python strings are correct? (Choose exactly 2 correct answers.)

Select 2 answers
A.Strings are mutable; you can change individual characters via indexing.
B.Strings have an .append() method to add characters at the end.
C.Strings are immutable; operations like concatenation produce a new string.
D.The + operator on strings creates a new string object containing the concatenated result.
E.You can assign a new character to a position in a string using indexing: s[0] = 'a'.
AnswersC, D

Immutability is a core property of Python strings: there is no in-place operation that modifies the characters or length of an existing str. Concatenation, for example with s1 + s2, does not extend s1; it allocates a new string whose content is the combined characters, leaving both operands untouched. This guarantee makes strings safe to use as dictionary keys and allows the interpreter to share or cache them.

Why this answer

Python strings are immutable, meaning once a string object is created, its content cannot be changed. Any operation that appears to modify a string, such as concatenation with the + operator, actually creates a brand-new string object in memory, leaving the original unchanged.

Exam trap

The PCAP exam often tests the immutability of strings by presenting options that imply strings behave like lists (e.g., item assignment or .append()), hoping candidates confuse string and list operations.

169
Multi-Selectmedium

Which TWO of the following statements about Python packages are true?

Select 2 answers
A.A package can contain subpackages.
B.An __init__.py file can be empty.
C.Packages cannot be imported using the import statement with dot notation.
D.An __init__.py file is required in every directory to make it a package.
E.A package is a single .py file.
AnswersA, B

A package can contain subpackages. This is correct because packages are essentially directories that map to importable namespaces, and those directories can contain other package directories. When a package directory contains an `__init__.py` (or qualifies as a namespace package), its subdirectories with `__init__.py` become subpackages, allowing hierarchical imports such as `import parent.child.module`. This nesting is fundamental to organizing large projects into logical, reusable components without forcing every module to live at the top level.

Why this answer

Python packages are directories that can contain subpackages (nested directories with their own __init__.py files), forming a hierarchical namespace. This allows for organized module grouping, such as `package.subpackage.module`, which is a core feature of Python's module system.

Exam trap

Python Institute often tests the misconception that an __init__.py file is always required for a directory to be a package, but since Python 3.3, namespace packages without __init__.py are valid, making option D a classic trap.

170
MCQeasy

A developer wants to check if a string 'racecar' is a palindrome by comparing it to its reverse. Which code completes the task correctly?

A.reversed(s) == s
B.s[::1] == s
C.s[::-1] == s
D.s.reverse() == s
AnswerC

The slice s[::-1] uses a negative step with default start and end, which makes Python traverse the string from the last character back to the first, producing the reversed string. Comparing this reversed result to the original string with == correctly determines whether s reads the same forward and backward, i.e., whether it is a palindrome.

Why this answer

The slicing syntax `s[::-1]` creates a reversed copy of the string `s`, and comparing it to `s` with `==` checks if the string reads the same forwards and backwards, which is the definition of a palindrome. For the string 'racecar', `s[::-1]` returns 'racecar', so the comparison is `True`.

Exam trap

The PCAP exam often tests the distinction between `reversed()` (which returns an iterator) and `[::-1]` (which returns a reversed sequence), and the fact that strings are immutable and lack a `.reverse()` method, leading candidates to confuse list methods with string operations.

How to eliminate wrong answers

Option A is wrong because `reversed(s)` returns a reverse iterator object, not a string, so comparing it to `s` with `==` will always be `False` (they are different types). Option B is wrong because `s[::1]` returns the string unchanged (step 1 from start to end), so it compares the string to itself and always returns `True`, not checking for palindrome. Option D is wrong because strings in Python have no `.reverse()` method; that method exists only for lists, so this would raise an `AttributeError`.

171
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.

172
MCQhard

Which of the following correctly raises a new exception while preserving the original traceback?

A.raise original_exception
B.raise ValueError('new')
C.raise ValueError('new') from original_exception
D.raise
AnswerC

This is the correct form for explicitly chaining a new exception to an existing one. The `from original_exception` clause makes Python assign the original to the new `ValueError`'s `__cause__` attribute, causing the traceback to present the original as the direct cause of the new exception. This preserves the debugging information from the original failure while still allowing a distinct exception type to be raised.

Why this answer

The `raise ... from original_exception` syntax in Python allows you to raise a new exception while chaining it to the original exception, preserving the original traceback. This is essential for debugging, as it shows both the new error and the root cause.

Exam trap

Python Institute often tests the distinction between re-raising the same exception (bare `raise` or `raise original_exception`) and raising a new exception with chaining (`raise ... from original_exception`), trapping candidates who think any `raise` preserves the traceback.

How to eliminate wrong answers

Option A is wrong because `raise original_exception` re-raises the exact same exception object, not a new one, so it does not create a new exception. Option B is wrong because `raise ValueError('new')` raises a brand-new exception without any reference to the original, losing the original traceback entirely. Option D is wrong because a bare `raise` can only be used inside an except block to re-raise the current exception; outside an except block it raises a RuntimeError, and it does not create a new exception.

173
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.

174
MCQhard

What is the likely outcome of running the following code? ```python with open("C:\Users\path\file.txt", "r") as f: print(f.read()) ```

A.The program raises a SyntaxError due to invalid escape sequences.
B.The program runs but the file contents are incorrect.
C.The program raises a FileNotFoundError because the path is invalid after escape interpretation.
D.The file is opened successfully because backslashes are ignored.
AnswerA

A normal string literal is parsed by the Python compiler before any code executes, and every backslash must form a legal escape sequence. `\U` is the escape prefix for a 32-bit Unicode code point and must be followed by exactly eight hexadecimal digits; here it is truncated, so the tokenizer raises `SyntaxError: (unicode error) ... truncated \UXXXXXXXX escape` at compile time. Consequently, no program output or file operation ever occurs.

Why this answer

The code likely contains backslash sequences (e.g., `\U`, `\p`, or other non-standard escapes) that are not valid escape sequences in Python. Starting with Python 3.12, such invalid sequences raise a `SyntaxError` at compile time, preventing the program from running. In earlier versions, a `DeprecationWarning` is issued, but the code may run.

The error is not about file operations or path resolution; it's a compile-time syntax error. To avoid this, use raw strings (`r"..."`) or double backslashes (`\\`).

Exam trap

Python Institute often tests the misconception that backslashes in strings are always treated literally or that invalid escape sequences are silently ignored, leading candidates to choose options about file operations instead of recognizing the compile-time SyntaxError.

How to eliminate wrong answers

Option B is wrong because the program does not run at all; a SyntaxError prevents execution, so no file is written or read. Option C is wrong because the error is a SyntaxError at compile time, not a runtime FileNotFoundError; the path string is never evaluated as a file path. Option D is wrong because backslashes are not ignored; they are interpreted as escape sequences, and invalid ones cause a SyntaxError.

175
Multi-Selecteasy

Which TWO of the following are valid ways to import specific names from a module?

Select 2 answers
A.from module import * (only names listed in __all__)
B.from module import name1, name2
C.from module import name as alias
D.import name1, name2 from module
E.import module.name1
AnswersB, C

This is the canonical Python syntax for importing one or more specific names directly into the current namespace. When you write `from module import name1, name2`, Python loads the entire module, but only the named attributes become local bindings—`name1` and `name2` are immediately accessible without any module prefix. This form gives you precise control over which objects you bring into scope, avoiding all extraneous names and clearly documenting the dependencies of your code.

Why this answer

The `from module import name1, name2` syntax allows importing specific names from a module directly into the current namespace. Option C is also correct because `from module import name as alias` provides the same functionality while allowing you to rename the imported name to avoid naming conflicts.

Exam trap

Python Institute often tests the distinction between `import module.name` (which is invalid for importing a specific name) and `from module import name` (which is correct), leading candidates to mistakenly think dot notation can import individual attributes.

176
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.

177
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'.

178
Multi-Selecthard

Which three of the following statements about Python strings are true? (Choose three.)

Select 3 answers
A.The join() method is called on the separator string.
B.The string '123.45' can be converted to integer using int('123.45').
C.Strings support indexing with integers.
D.Strings are mutable.
E.The len() function returns the number of characters including spaces.
AnswersA, C, E

The join() method is invoked on the separator string, and it takes an iterable of strings as its argument. For example, ','.join(['a', 'b']) returns 'a,b' by inserting the separator between each pair of elements. The separator string is not modified; it is reused as the delimiter, and every element in the iterable must be a string or a TypeError will be raised.

Why this answer

The join() method is called on the separator string, not on the iterable. For example, ','.join(['a', 'b']) returns 'a,b'. The separator is the string that will be placed between each element of the iterable passed as an argument.

This is a common point of confusion because many learners mistakenly think join() is called on the list.

Exam trap

PCAP often tests the immutability of strings by presenting a statement that suggests strings can be changed in place, catching candidates who confuse strings with mutable sequence types like lists.

179
MCQeasy

What is the output of the code in the exhibit?

A.{name} is {age} years old.
B.Alice is 30 years old.
C.name is age years old.
D.30 is Alice years old.
AnswerB

The f-string's placeholders are evaluated at runtime: {name} is replaced by the value of the variable name, which is 'Alice', and {age} is replaced by the value of age, which is 30. The resulting concatenated string matches exactly this output, making it the correct answer.

Why this answer

The code uses an f-string which substitutes the values of the variables `name` and `age` into the string. Evaluating the expression results in 'Alice is 30 years old.', matching option B. Option A shows the literal braces, option C displays the variable names instead of their values, and option D reverses the order of the variables.

Exam trap

The trap here is that candidates may confuse f-strings with regular strings and think the literal text {name} and {age} is printed, or they may misorder the variables in the output, leading them to choose option A or D instead of recognizing the correct substitution.

How to eliminate wrong answers

Option A is wrong because it shows the raw f-string template with {name} and {age} unsubstituted, which would only appear if the string were printed without the 'f' prefix or if the variables were not defined. Option C is wrong because it is identical to option B, but the question expects the exact output including the period at the end; however, both B and C are the same string, so the correct answer is B as marked. Option D is wrong because it reverses the order of the variables, placing age before name, which does not match the f-string's defined order in the code.

180
MCQmedium

A developer is working on a project that requires the use of a third-party package hosted on a private repository. The developer wants to ensure that the package can be imported without specifying the full repository URL each time. Which approach should be taken?

A.Append the repository path to sys.path in the script.
B.Place the package files in the site-packages directory manually.
C.Configure the repository URL in pip's configuration file or in requirements.txt.
D.Use os.system to run a pip install command from within the script.
AnswerC

This is the standard, reproducible way to make Python's packaging tooling use a private or alternate repository: specify an index URL via index-url or extra-index-url in pip.conf, or use a fully-qualified requirement line (e.g., --extra-index-url) in requirements.txt. During installation, pip queries the configured indexes, resolves the complete dependency graph, and installs the package plus all of its dependencies into site-packages as wheel or sdist distributions. This method respects version constraints, generates proper distribution metadata, and works consistently across environments because the configuration is declarative and versionable.

Why this answer

Configuring the repository URL in pip's configuration file (e.g., `pip.conf`, `pip.ini`, or `~/.config/pip/pip.conf`) or in `requirements.txt` using the `--index-url` or `--extra-index-url` option allows pip to resolve the package from the private repository automatically. This approach ensures that the package can be installed and imported without manually specifying the full URL each time, as pip will use the configured index to locate and download the package.

Exam trap

Python Institute often tests the distinction between runtime import path manipulation (like `sys.path`) and package installation configuration, trapping candidates who confuse adding a directory to `sys.path` with configuring a remote package index for pip.

How to eliminate wrong answers

Option A is wrong because appending the repository path to `sys.path` only adds a directory to Python's module search path, which is used for importing already-installed modules; it does not install the package from a remote repository or resolve dependencies. Option B is wrong because manually placing package files in `site-packages` bypasses pip's dependency resolution, version management, and integrity checks, leading to potential conflicts or incomplete installations. Option D is wrong because using `os.system` to run a pip install command from within the script is a fragile, non-portable approach that mixes installation logic with runtime code, and it does not provide a persistent configuration for future imports.

181
MCQeasy

Which of the following is the correct way to open a file for writing in binary mode?

A.open('data.dat', 'wb')
B.open('data.dat', 'bw')
C.open('data.dat', 'br')
D.open('data.dat', 'w')
AnswerA

The mode string 'wb' is the correct Python file mode for binary writing. The first character 'w' specifies the operation (write), and the second character 'b' explicitly selects binary mode rather than text mode. This mode both creates the file if it does not exist and truncates it to zero length if it does, allowing you to write raw bytes without any encoding or newline translation.

Why this answer

The mode string 'wb' specifies both write ('w') and binary ('b') mode, which is the proper way to open a file for writing binary data in Python. The order of characters in the mode string is fixed: the file mode character ('r', 'w', 'a', etc.) must come first, followed by the optional 'b' for binary mode.

Exam trap

Python Institute often tests the strict ordering of mode characters in the open() function, expecting candidates to know that 'b' must always follow the read/write/append character, not precede it.

How to eliminate wrong answers

Option B is wrong because 'bw' reverses the required order — the mode character ('w') must precede the binary modifier ('b'), and Python will raise a ValueError for an invalid mode string. Option C is wrong because 'br' opens the file for reading in binary mode, not writing. Option D is wrong because 'w' opens the file for writing in text mode, not binary mode, which can cause data corruption when writing non-text data (e.g., images or serialized objects) due to newline translation.

182
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.

183
MCQeasy

A junior developer is writing a script that processes user input. The script reads a line of text from the console and needs to remove any leading or trailing whitespace. The developer uses the strip() method but notices that it also removes other characters like newline. However, the requirement is to remove only spaces (not tabs or newlines). Which course of action should the developer take to remove only leading and trailing spaces?

A.Use replace(' ', '') on the string
B.Use lstrip() and rstrip() with no arguments
C.Use split() and join()
D.Use strip(' ') with a space argument
AnswerD

Passing a space as the argument restricts strip() to that character set only, so leading and trailing spaces are removed while tabs, newlines and other whitespace remain intact. The bare strip() call would strip all whitespace types, violating the stated requirement.

Why this answer

The strip() method in Python, when called with no arguments, removes all leading and trailing whitespace characters, including spaces, tabs, and newlines. By passing a space character as the argument, strip(' '), the method is instructed to remove only that specific character (space) from the ends of the string, leaving tabs and newlines intact. This directly meets the requirement to remove only leading and trailing spaces.

Exam trap

The trap here is that candidates often assume strip() without arguments only removes spaces, but the PCAP exam tests the nuance that strip() by default removes all whitespace characters, and that passing a specific character as an argument restricts the removal to that character only.

How to eliminate wrong answers

Option A is wrong because replace(' ', '') removes all spaces everywhere in the string, not just leading and trailing ones, which would alter the internal content of the string. Option B is wrong because lstrip() and rstrip() with no arguments remove all leading and trailing whitespace (including tabs and newlines), which is exactly what the developer wants to avoid. Option C is wrong because split() and join() would split the string on whitespace and rejoin it, which removes all whitespace (including internal spaces) and does not specifically target only leading and trailing spaces.

184
MCQhard

Given the code: s = 'Python'; t = s; s = s + '3.0'. What is the value of t after these lines execute?

A.It raises an error because s was reassigned.
B.''
C.'Python3.0'
D.'Python'
AnswerD

When t = s executes, both variables reference the same immutable string object containing 'Python'. Later, s = s + '3.0' creates a new string object and rebinds only s; t remains bound to the original object. Therefore printing t outputs 'Python'.

Why this answer

Strings in Python are immutable. The assignment `t = s` makes `t` reference the same string object as `s`. When `s = s + '3.0'` executes, a new string object `'Python3.0'` is created and bound to `s`, while `t` still references the original string `'Python'`.

Thus, `t` remains `'Python'`.

Exam trap

Python Institute often tests the misconception that variable assignment creates a copy of the value, when in fact it creates a reference; candidates mistakenly think `t` will reflect the new value of `s` after reassignment.

How to eliminate wrong answers

Option A is wrong because reassigning `s` does not raise an error; Python allows variable reassignment freely. Option B is wrong because `t` is never assigned an empty string; it is assigned the original value of `s`, which is `'Python'`. Option C is wrong because `t` does not get updated when `s` is reassigned; `t` still points to the original immutable string `'Python'`, not the new concatenated string `'Python3.0'`.

185
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.

186
Multi-Selecteasy

Which TWO of the following are built-in exceptions in Python? (Select exactly 2.)

Select 2 answers
A.InputError
B.ValueError
C.DataError
D.FileNotFoundError
E.CustomError
AnswersB, D

ValueError is a built-in exception and belongs to the Exception hierarchy, directly under Exception (and ultimately under BaseException). It is raised when a function receives an argument of the correct type but an inappropriate value—for example, int('abc') raises ValueError because the string cannot be converted to an integer. This distinguishes it from TypeError, which is for wrong types, and from other built-in exceptions that signal different error conditions.

Why this answer

ValueError is a built-in exception in Python, raised when a built-in operation or function receives an argument with the correct type but an inappropriate value, such as int('abc'). It is part of Python's standard exception hierarchy and does not require any import.

Exam trap

Python Institute often tests candidates by including plausible-sounding exception names like InputError or DataError that mimic real-world patterns but are not part of Python's built-in exception hierarchy, leading candidates to confuse custom or third-party exceptions with standard ones.

187
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.

188
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.

189
MCQeasy

Consider the following code: import json try: with open('config.json') as f: data = json.load(f) except FileNotFoundError: print("Missing config file") except json.JSONDecodeError: print("Invalid JSON") except: print("Unexpected error") If the file 'config.json' exists but contains invalid JSON, what is printed?

A.Unexpected error
B.The program crashes with an unhandled exception.
C.Missing config file
D.Invalid JSON
AnswerD

Invalid JSON is correct because the file exists and is readable, but its content cannot be parsed by json.load() or json.loads(). The json module raises json.JSONDecodeError, a subclass of ValueError, when the data does not conform to JSON syntax. The program's except block catches this exception, confirming the specific outcome is "Invalid JSON" rather than any file-system error.

Why this answer

When the file exists but contains invalid JSON, attempting to parse it raises a json.JSONDecodeError. A program designed to handle this exception will catch it and print 'Invalid JSON', as indicated by option D. Options A and B are incorrect because the error is specifically a JSON parsing error, not an unexpected error or an unhandled crash.

Option C is incorrect because the file does exist, so no file-not-found error occurs.

Exam trap

Python Institute often tests the distinction between file existence errors (`FileNotFoundError`) and content parsing errors (`json.JSONDecodeError`), trapping candidates who assume any file problem results in a generic crash or a missing-file message.

How to eliminate wrong answers

Option A is wrong because 'Unexpected error' is not printed; the code has a specific handler for invalid JSON, not a generic catch-all. Option B is wrong because the program does not crash; the exception is caught, preventing an unhandled crash. Option C is wrong because 'Missing config file' is only printed if `FileNotFoundError` is raised, which requires the file to be absent, but the file exists (albeit with invalid content).

190
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.

191
MCQhard

Refer to the exhibit. What is the output?

A.Hi, World!
B.Hello, World!
C.HELLO, WORLD!
D.HI, WORLD!
AnswerD

This is the correct result after executing both operations in sequence: first, replace("Hello", "Hi") changes the string to "Hi, World!"; second, upper() converts every alphabetic character to uppercase, producing "HI, WORLD!". The order of the chain matters—the replacement happens before case conversion, so the greeting becomes "HI" instead of "HELLO", matching the exhibited output exactly.

Why this answer

The code uses the `upper()` method on the string `'Hi, World!'`, which converts all lowercase letters to uppercase. The output is `'HI, WORLD!'`. The `upper()` method does not modify the original string but returns a new string with all characters in uppercase.

Exam trap

Python Institute often tests whether candidates notice the exact original string value, as many mistakenly assume the output is 'HELLO, WORLD!' from a common greeting like 'Hello, World!' rather than the actual string 'Hi, World!'.

How to eliminate wrong answers

Option A is wrong because it shows the original string unchanged, but the `upper()` method was called, so the output must be all uppercase. Option B is wrong because it shows 'Hello, World!' which is a different string entirely, not the result of calling `upper()` on `'Hi, World!'`. Option C is wrong because it shows 'HELLO, WORLD!' which would be the result of calling `upper()` on 'Hello, World!', not on 'Hi, World!'.

192
Multi-Selecteasy

Which TWO of the following are valid ways to define a property in a Python class? (Select exactly 2.)

Select 2 answers
A.Define a method named `property` inside the class.
B.Override `__getattribute__` and check the attribute name.
C.Override `__getattr__` to simulate a property.
D.Use `property(getter, setter)` as a class variable.
E.Use the @property decorator on a method.
AnswersD, E

Assigning `property(getter, setter)` as a class variable directly creates a data descriptor that manages a specific attribute. Because `property` is a class implementing `__get__` and `__set__`, Python calls the supplied getter and setter functions whenever the attribute is accessed or assigned. This functional form is valid and is equivalent to the decorator form, though less commonly used in modern code.

Why this answer

`property(getter, setter)` is a built-in function that returns a property object, which can be assigned as a class variable to define a managed attribute. Option E is correct because the `@property` decorator is the standard, concise way to define a read-only property by decorating a method that acts as the getter.

Exam trap

Python Institute often tests the distinction between defining a property via the `property()` function or `@property` decorator versus overriding dunder methods like `__getattr__` or `__getattribute__`, which are attribute interception hooks, not property definitions.

193
MCQhard

Which of the following expressions returns True if the string s contains only hexadecimal digits (0-9, a-f, A-F)?

A.s.isdigit() or s.isalpha()
B.s.isnumeric()
C.s.isalnum() and s.islower()
D.all(c in '0123456789abcdefABCDEF' for c in s)
AnswerD

This is correct because it explicitly tests each character against the exact set of valid hexadecimal digits, '0123456789abcdefABCDEF', using the all() function with a generator expression. Every character in s must be a member of that set for the expression to evaluate to True. One subtlety is that all() returns True for an empty string, so if an empty input should be considered invalid, an additional length check is needed.

Why this answer

It explicitly checks each character in the string against the set of valid hexadecimal digits (0-9, a-f, A-F) using the `all()` function. This ensures that every character is a hex digit, which is the precise requirement for a string to contain only hexadecimal digits.

Exam trap

The PCAP exam often tests the misconception that `isalnum()` or `isdigit()` combined with `isalpha()` can validate hex digits, but they fail because they do not restrict letters to the a-f/A-F range and may accept non-ASCII characters.

How to eliminate wrong answers

Option A is wrong because `s.isdigit()` returns True only for decimal digits (0-9), and `s.isalpha()` returns True only for alphabetic characters; combining them with `or` would accept strings that are entirely digits or entirely letters, but not necessarily hex digits (e.g., 'g' would pass isalpha but is not a hex digit). Option B is wrong because `s.isnumeric()` returns True for any numeric characters including Unicode numerals (e.g., ², ½) and decimal digits, but it does not accept letters a-f/A-F, so it would reject valid hex strings like '1a'. Option C is wrong because `s.isalnum()` returns True if all characters are alphanumeric (letters or digits), but it does not restrict letters to a-f/A-F (e.g., 'g' would pass), and `s.islower()` would reject strings containing uppercase hex letters like 'A', making it too restrictive.

194
MCQmedium

A developer runs a script that reads records from a binary file. After a partial read, the storage device is unplugged, and the read() call raises OSError. The developer wants the script to retry the read a few times before giving up, but only for this transient I/O problem. Which exception should be caught to retry specifically on this failure?

A.RuntimeError
B.EOFError
C.OSError
D.IOError
AnswerC

OSError is the base class for I/O failures such as a device being unplugged, and read() raises it when the underlying read fails. Catching OSError around the read allows a bounded retry loop for this transient hardware problem, while still letting unrelated errors propagate. Because FileNotFoundError and PermissionError inherit from OSError, the handler should inspect errno or use a narrower subclass if those must be handled differently.

Why this answer

A transient device failure during read() surfaces as OSError, the common base for I/O errors. Catching it around the read permits a bounded retry while still allowing non-I/O exceptions to propagate. The other listed exceptions describe unrelated conditions and would not catch this failure, so they cannot drive the retry behavior the scenario requires.

Exam trap

The trap here is assuming that IOError is a separate, more specific exception from OSError, when in Python 3 IOError is just an alias for OSError.

195
MCQhard

An application needs to dynamically load a module whose name is provided at runtime (stored in a variable 'mod_name'). Which function from the importlib module should be used?

A.importlib.reload(mod_name)
B.importlib.load_module(mod_name)
C.importlib.import(mod_name)
D.importlib.import_module(mod_name)
AnswerD

importlib.import_module(mod_name) is the correct way to dynamically load a module when its name is only known at runtime, because it accepts a string and returns the corresponding module object while registering it in sys.modules. It uses the standard import machinery, supports both absolute and relative imports (with a package argument), and is designed exactly for this programmatic use case. This makes it the appropriate replacement for older, deprecated functions like load_module.

Why this answer

`importlib.import_module(mod_name)` is the standard Python function designed to dynamically import a module given its name as a string at runtime. It returns the module object, allowing the application to load and use modules whose names are not known until execution.

Exam trap

Python Institute often tests the distinction between `importlib.import_module()` and the non-existent `importlib.import()` or the deprecated `imp.load_module()`, exploiting candidates' tendency to guess based on similar-sounding names rather than precise API knowledge.

How to eliminate wrong answers

Option A is wrong because `importlib.reload()` is used to re-import an already loaded module, not to load a module by name for the first time. Option B is wrong because `importlib.load_module()` does not exist in the standard `importlib` module; it was part of the deprecated `imp` module. Option C is wrong because `importlib.import()` is not a valid function; the correct function name is `import_module`, not `import`.

196
Multi-Selecthard

Which THREE statements about the Python method resolution order (MRO) are true? (Select exactly 3.)

Select 3 answers
A.The MRO is determined at runtime when a method is called.
B.The MRO of a class can be viewed using the __mro__ attribute.
C.C3 linearization is the algorithm used for MRO in Python 3.
D.Python uses a depth-first left-to-right algorithm for MRO.
E.super() uses the MRO to determine which method to call.
AnswersB, C, E

Every Python class exposes a read-only __mro__ attribute that is a tuple of classes in the exact order Python will search for attributes and methods. The tuple starts with the class itself, then its ancestors in C3-linearized order, and ends with object. This attribute is the canonical way to inspect the method resolution order, for example by printing MyClass.__mro__.

Why this answer

The `__mro__` attribute on a class returns a tuple of classes in the exact order that Python uses to resolve methods and attributes. This attribute is computed at class definition time using the C3 linearization algorithm, and it provides a direct, read-only view of the resolution order for that class.

Exam trap

Python Institute often tests the misconception that MRO is determined dynamically at runtime (option A) or that Python still uses a simple depth-first left-to-right algorithm (option D), when in fact Python 3 exclusively uses the C3 linearization algorithm computed at class definition time.

197
Matchingmedium

Match each Python built-in function to its description.

Drag a concept onto its matching description — or click a concept then click the description.

Concepts
Matches

Returns the length of an object

Generates a sequence of numbers

Returns a sorted list from an iterable

Returns index and value pairs

Aggregates elements from multiple iterables

Why these pairings

The correct matches are: len() returns length, map() applies a function, filter() filters by truth, zip() combines iterables. Common confusions involve swapping the definitions of map and len, or filter and zip.

198
MCQeasy

A developer is formatting a log message and wants to ensure that a string variable `name` is centered within a field of width 20, padded with asterisks (`*`) on both sides. For example, if `name = "Alice"`, the result should be `*******Alice********` (7 asterisks on the left, 8 on the right). Which method call achieves this?

A.name.rjust(20, '*')
B.name.ljust(20, '*')
C.name.center(20, '*')
D.name.zfill(20)
AnswerC

The str.center(width, fillchar) method returns a new string of length width, with the original string centered and padded with the specified fill character. For 'Alice' and width 20, the total padding is 15 characters. Python puts the extra padding on the right when the padding is odd, resulting in 7 asterisks on the left and 8 on the right, exactly as required.

Why this answer

To center a string within a field and pad with a specific character, the str.center() method is used. It takes the desired width and an optional fill character. When the total padding is odd, Python places the extra character on the right, matching the example.

The other methods either left-justify, right-justify, or pad with zeros, none of which produce a centered result with asterisks on both sides.

Exam trap

The trap here is mixing up the justification methods and forgetting that center() places extra padding on the right when the total padding is odd.

199
Multi-Selecteasy

Which TWO statements about static methods (@staticmethod) are correct?

Select 2 answers
A.They do not receive an implicit first argument.
B.They can access instance attributes via self.
C.They can access class variables only via cls.
D.They are defined using the @staticmethod decorator.
E.They can only be defined inside a metaclass.
AnswersA, D

Static methods are not bound to either an instance or the class, so Python passes no implicit first argument when they are invoked. Unlike instance methods which receive self or class methods which receive cls, a static method's signature matches exactly what is written in the function definition. This makes them behave like ordinary functions, but they still live in the class's namespace.

Why this answer

Static methods in Python do not receive an implicit first argument like `self` (for instance methods) or `cls` (for class methods). They behave like plain functions but belong to a class's namespace, and are called without any automatic parameter injection.

Exam trap

Python Institute often tests the distinction between `@staticmethod` and `@classmethod`, and the trap here is that candidates confuse static methods with class methods, assuming static methods can access class variables via `cls` or instance attributes via `self`.

200
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.

201
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.

202
Multi-Selecthard

Which THREE of the following are true about Python's object-oriented programming features?

Select 3 answers
A.Python supports method overloading based on argument types
B.Python supports multiple inheritance
C.All methods are virtual in the sense that they can be overridden
D.Python enforces access modifiers like private and protected
E.Operator overloading can be implemented by defining special methods like __add__
AnswersB, C, E

Multiple inheritance is a first-class feature in Python: class Derived(Base1, Base2) creates a class that inherits attributes and methods from all listed base classes. To resolve conflicts, Python computes a linearization order (MRO) using the C3 algorithm, which determines the sequence in which base classes are searched for attributes. This MRO also enables cooperative behavior with super(), making mixin classes a common and safe pattern, though diamond hierarchies require deliberate design.

Why this answer

Python's class hierarchy supports multiple inheritance, allowing a class to inherit from more than one parent class. This is a core feature of Python's object-oriented programming model, implemented via the C3 linearization algorithm (Method Resolution Order, or MRO) to resolve method and attribute lookups unambiguously.

Exam trap

Python Institute often tests the misconception that Python supports method overloading like Java or C++, leading candidates to incorrectly select Option A, when in fact Python uses dynamic typing and late binding to handle different argument patterns through default or variable arguments.

203
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`).

204
MCQhard

A data-import tool must read a UTF-8 CSV file that occasionally contains bytes invalid for UTF-8. The tool should not crash, but it must record that replacement occurred so the operator can review the source. The developer opens the file with `open('data.csv', encoding='utf-8', errors='replace')` and reads it. Which outcome matches this configuration?

A.Each invalid byte sequence is replaced by U+FFFD, and the tool can scan for that character to detect and count problems.
B.Invalid bytes are silently removed from the decoded string, leaving no trace in the text.
C.The decoder substitutes a question mark character and logs a warning through the warnings module automatically.
D.Decoding invalid bytes raises UnicodeDecodeError, and the handler in the tool catches it per line.
AnswerA

The replace error handler substitutes the Unicode replacement character U+FFFD wherever the decoder encounters an invalid sequence. The resulting string is valid and the read does not raise, so the tool can search for U+FFFD to count and locate suspect regions. This matches the requirement to continue processing while recording that replacement occurred.

Why this answer

Passing errors='replace' to open installs an error handler that substitutes U+FFFD for every invalid byte sequence during decoding. The read completes without raising, producing a valid string that still carries visible markers of corruption. Scanning the decoded text for U+FFFD lets the tool count and report affected records, satisfying both the no-crash and traceability requirements.

Exam trap

The trap here is confusing errors='replace' with errors='ignore', assuming corruption disappears silently rather than leaving the visible U+FFFD replacement character in the decoded string.

205
Multi-Selecthard

Which THREE of the following are true about Python's exception hierarchy?

Select 3 answers
A.KeyboardInterrupt inherits from BaseException.
B.SystemExit inherits from BaseException.
C.IOError is a separate class from OSError.
D.ZeroDivisionError inherits from ArithmeticError.
E.GeneratorExit inherits from Exception.
AnswersA, B, D

KeyboardInterrupt is a true statement because KeyboardInterrupt is a direct subclass of BaseException, not of Exception. This design ensures that a KeyboardInterrupt triggered by Ctrl+C propagates outward even when code has a broad `except Exception:` handler. Catching it accidentally would prevent clean interruption and could leave the program in an inconsistent state, so it must be caught explicitly with `except KeyboardInterrupt` or a bare `except:`. The hierarchy deliberately places user-initiated termination outside the ordinary exception family.

Why this answer

`KeyboardInterrupt` inherits directly from `BaseException`, not from `Exception`. This design ensures that `KeyboardInterrupt` (raised by Ctrl+C) is not caught by a generic `except Exception:` clause, allowing the program to be interrupted even when broad exception handling is in place.

Exam trap

Python Institute often tests the misconception that `GeneratorExit` inherits from `Exception` (it actually inherits from `BaseException`), and that `IOError` is a separate class from `OSError` (it is an alias in Python 3).

206
MCQeasy

A developer wants to distribute a package that contains both Python code and data files (e.g., images, configs). Which file is used to specify dependencies and metadata for the package?

A.setup.py
B.MANIFEST.in
C.__init__.py
D.requirements.txt
AnswerA

setup.py is the standard configuration and build script for Python packages, used by setuptools (or distutils) to define all distribution metadata—such as the package name, version, description, authors, and, crucially, dependencies via the `install_requires` keyword. When a developer runs commands like `python setup.py sdist` or `bdist_wheel`, this file is the source of truth for what goes into the package and what dependencies it declares, making it the correct place to specify the dependency on the other custom module.

Why this answer

setup.py is the standard file used to specify metadata and dependencies for a Python package. It contains information such as the package name, version, author, and a list of required packages (install_requires). It is used by setuptools to build and distribute the package.

Exam trap

PCAP often tests the confusion between setup.py and requirements.txt, where candidates might think requirements.txt is used for package metadata, but it is only for dependency listing.

How to eliminate wrong answers

Option B is wrong because MANIFEST.in is used to specify additional files to include in the source distribution, such as data files, but it does not specify dependencies or metadata. Option C is wrong because __init__.py is used to mark a directory as a Python package, but it does not contain package metadata or dependency information. Option D is wrong because requirements.txt is used to list dependencies for a specific environment, but it is not used for packaging metadata; it is typically for development or deployment, not for distribution.

207
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() returns a copy with leading whitespace characters removed, leaving trailing and internal whitespace untouched. This matches the stem's constraint precisely, since only leading spaces, tabs and newlines must be stripped, and lstrip() is a built-in string method requiring no import.

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.

208
Multi-Selecteasy

Which of the following statements about class inheritance in Python are true? (Choose two.)

Select 2 answers
A.A class can inherit from only one base class.
B.Abstract base classes can be defined using the ABC module.
C.A child class can override any method from its parent class, but only if the method is declared as virtual.
D.The super() function is used to call a method from a sibling class.
E.Python supports multiple inheritance.
AnswersB, E

The abc module in Python's standard library supplies the ABC metaclass-derived helper class and the abstractmethod decorator for defining abstract base classes. Marking a method with @abstractmethod forces any concrete subclass to implement it before it can be instantiated; attempting to instantiate an unfinished subclass raises TypeError. This gives developers a robust mechanism for enforcing interface contracts in a dynamically typed language.

Why this answer

Python's `abc` module (Abstract Base Classes) allows you to define abstract base classes by inheriting from `ABC` and using the `@abstractmethod` decorator. This enforces that subclasses must implement the abstract methods, providing a formal interface contract.

Exam trap

Python Institute often tests the misconception that `super()` only calls a parent method, but in multiple inheritance it actually calls the next class in the MRO, which could be a sibling or a cousin, not necessarily a direct parent.

209
MCQeasy

A developer is implementing a simple counter class. The class should start at 0 and increment by 1 each time the 'increment' method is called. Which implementation is correct?

A.class Counter:\n def __init__(self):\n self.count = 0\n def increment(self):\n count = self.count + 1
B.class Counter:\n def __init__(self):\n self.count = 0\n def increment(self):\n self.count += 1
C.class Counter:\n def __init__(self):\n count = 0\n def increment(self):\n count += 1
D.class Counter:\n def __init__(self):\n self.count = 0\n def increment():\n self.count += 1
AnswerB

This is the correct implementation because self.count += 1 is syntactic sugar for self.count = self.count + 1, which rebinds the instance attribute to its own current value plus one. The method receives the instance through the mandatory self parameter, so each call persists the updated count on the object. This follows the standard pattern for mutating instance state and produces the expected cumulative behavior across multiple calls.

Why this answer

It properly initializes an instance variable `self.count` to 0 in the `__init__` method and then uses `self.count += 1` in the `increment` method to modify the instance variable in place. The `+=` operator is a shorthand for `self.count = self.count + 1`, which correctly updates the counter each time `increment` is called.

Exam trap

Python Institute often tests the distinction between local variables and instance variables in methods, trapping candidates who forget to prefix `self` when accessing or modifying object attributes.

How to eliminate wrong answers

Option A is wrong because `count = self.count + 1` creates a local variable `count` inside the `increment` method instead of updating the instance variable `self.count`, so the counter never changes. Option C is wrong because `count = 0` in `__init__` creates a local variable instead of an instance variable, and `count += 1` in `increment` tries to modify a local variable that hasn't been initialized in that scope, causing a `NameError`. Option D is wrong because the `increment` method is missing the required `self` parameter, so calling `increment()` will raise a `TypeError` about missing positional arguments.

210
MCQmedium

When importing a module, Python searches for it in a specific order. Which of the following lists the correct order of directories searched?

A.PYTHONPATH then sys.path
B.[current directory] then PYTHONPATH then site-packages
C.sys.path + [current directory]
D.[current directory] + sys.path
AnswerB

This option incorrectly treats current directory, PYTHONPATH, and site-packages as three distinct search locations, whereas all are simply elements of the single sys.path list. The current directory (specifically the script's directory) is placed at sys.path[0], and PYTHONPATH directories are added immediately after it, while site-packages appears later, but the interpreter never performs separate 'phases' for these; it linearly walks the combined sys.path list. Moreover, the phrase 'current directory' is imprecise because Python uses the script's directory for file execution, not the process's current working directory.

Why this answer

When Python imports a module, it first searches the directory containing the input script (or current working directory), then iterates through the directories listed in the PYTHONPATH environment variable, and finally checks installation-dependent default paths such as site-packages. This order is reflected in sys.path, which is built from the script directory, PYTHONPATH entries, and default site-packages. Option B accurately lists this sequence: current directory, then PYTHONPATH, then site-packages.

Exam trap

Python Institute often tests the misconception that PYTHONPATH is searched before the current directory, or that sys.path is a static list rather than a dynamically built sequence starting with the script's directory.

How to eliminate wrong answers

Option A is wrong because PYTHONPATH is not searched before sys.path; rather, PYTHONPATH entries are inserted into sys.path after the current directory, so the search order is current directory, then PYTHONPATH, then site-packages. Option B is wrong because it omits the fact that the current directory is searched first, but it incorrectly lists 'site-packages' as a separate step after PYTHONPATH; in reality, site-packages is part of sys.path and is searched after PYTHONPATH, not as a distinct third step. Option C is wrong because it suggests that sys.path is searched before the current directory, which reverses the actual order; the current directory is always prepended to sys.path, making it the first location searched.

211
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.

212
MCQmedium

A developer wants to remove leading and trailing whitespace from a string. Which method should be used?

A.s.lstrip()
B.s.trim()
C.s.rstrip()
D.s.strip()
AnswerD

s.strip() correctly removes whitespace from both the beginning and the end of the string. For example, ' hello '.strip() returns 'hello', eliminating the leading and trailing spaces. Because it precisely matches the requirement, and because strings are immutable, it returns a new stripped string rather than modifying the original.

Why this answer

The `strip()` method in Python removes both leading and trailing whitespace (including spaces, tabs, and newlines) from a string. This is the standard method for trimming whitespace from both ends, as specified in Python's string documentation.

Exam trap

Python Institute often tests the distinction between `strip()`, `lstrip()`, and `rstrip()`, and the trap here is that candidates may confuse `strip()` with the non-existent `trim()` method from other languages, or think `lstrip()` or `rstrip()` alone suffice for full trimming.

How to eliminate wrong answers

Option A is wrong because `lstrip()` only removes leading whitespace from the left side, not trailing whitespace. Option B is wrong because `trim()` is not a valid Python string method; it exists in other languages like Java or JavaScript but not in Python. Option C is wrong because `rstrip()` only removes trailing whitespace from the right side, not leading whitespace.

213
MCQeasy

A programmer wants to ensure that a class attribute is the same for all instances and can be accessed via the class name. Which type of variable should be defined?

A.Global variable
B.Instance variable
C.Local variable inside a method
D.Class variable
AnswerD

A class variable is defined directly in the class body, making it part of the class namespace and shared by all instances of that class. It can be accessed via ClassName.variable or through an instance (unless shadowed by an instance attribute), and changes made through the class are visible to every instance. This matches the requirement for a class attribute that is common to the class rather than per-instance.

Why this answer

A class variable in Python is defined directly within the class body (outside any method) and is shared across all instances. It can be accessed via the class name (e.g., `ClassName.var`) or through any instance, ensuring the same value for all objects.

Exam trap

Python Institute often tests the misconception that a class variable can be safely modified via an instance, but the trap is that doing so creates an instance variable that shadows the class variable, leaving the original class variable unchanged for other instances.

How to eliminate wrong answers

Option A is wrong because a global variable is defined at the module level, not inside a class, and is not inherently tied to the class or its instances; it can be modified from anywhere, breaking encapsulation. Option B is wrong because an instance variable is unique to each object (defined with `self` in `__init__`), so it is not the same for all instances. Option C is wrong because a local variable inside a method exists only within that method's scope and cannot be accessed via the class name or by other methods.

214
MCQhard

A team is developing a banking system in Python. They have a base class Account with attributes account_number and balance, and a method __init__(self, account_number, balance) that initializes these attributes. They then create a subclass SavingsAccount that adds an attribute interest_rate. In SavingsAccount's __init__, they assign self.interest_rate = rate but do not call super().__init__. When they instantiate SavingsAccount('12345', 1000, 0.02) and attempt to print(balance), an AttributeError occurs: 'SavingsAccount' object has no attribute 'balance'. What is the most appropriate fix to ensure that the SavingsAccount includes balance and account_number without code duplication?

A.Remove the __init__ method from SavingsAccount entirely and rely on the default __init__ from Account.
B.Manually assign self.account_number and self.balance in SavingsAccount.__init__ before assigning interest_rate.
C.Call super().__init__(account_number, balance) as the first line in SavingsAccount.__init__, then assign self.interest_rate = rate.
D.Define balance as a class attribute in Account with a default value and remove it from __init__.
AnswerC

Calling super().__init__(account_number, balance) immediately at the start of SavingsAccount.__init__ delegates construction of base-class attributes to Account, preserving its invariants and any additional logic it performs. After the delegate call, assigning self.interest_rate = rate adds the subclass-specific attribute. This is the canonical cooperative-inheritance pattern and ensures the object is fully initialized before it is used.

Why this answer

In Python, the subclass SavingsAccount overrides __init__ but never invokes the parent's initializer, so account_number and balance are never set on the instance. Calling super().__init__(account_number, balance) as the first line of SavingsAccount.__init__ runs Account's initializer, which assigns those attributes, and then the subclass can safely set self.interest_rate = rate. This is the canonical cooperative-initialization pattern and avoids duplicating the parent's assignment logic.

Exam trap

The trap is that candidates see 'no code duplication' and jump to option B (manually assign the attributes) because it looks explicit and safe, missing that the question is testing the cooperative super().__init__ pattern as the idiomatic, non-duplicating fix.

How to eliminate wrong answers

Option A is wrong because removing SavingsAccount.__init__ would drop the interest_rate assignment entirely, and the default Account.__init__ signature would not accept the third positional argument. Option B is wrong because it duplicates the parent's attribute-assignment logic in the subclass, which is exactly the code duplication the question asks to avoid and breaks if Account's initialization changes. Option D is wrong because moving balance to a class attribute changes its semantics — it would be shared across instances and no longer set per-instance from the constructor argument.

215
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`.

216
Multi-Selectmedium

Which THREE of the following are true about the __pycache__ directory?

Select 3 answers
A.It is only created when the script is compiled with -O.
B.It is automatically created when a module is imported.
C.It improves startup time for subsequent runs.
D.It stores compiled bytecode files (.pyc).
E.It should be added to version control.
AnswersB, C, D

On the first import of a module, Python's import system compares the source file's timestamp or hash against any existing cached bytecode; if no matching `.pyc` exists, it compiles the module and writes the resulting bytecode into the `__pycache__` directory. This occurs transparently as part of the import machinery, with no explicit user action, and it does not apply to the top-level script executed with `python script.py`—only to modules that are imported.

Why this answer

Python automatically creates the __pycache__ directory when a module is imported for the first time. This directory stores compiled bytecode files (.pyc) that allow Python to skip recompilation on subsequent imports, thereby improving startup time for later runs.

Exam trap

Python Institute often tests the misconception that __pycache__ is only created with -O or that it should be version-controlled, when in fact it is automatically generated on import and is meant to be excluded from version control.

217
MCQmedium

Which of the following is the correct way to format a string to include a variable value with two decimal places in Python?

A.f"{value:.2f}"
B.f"{value:.2}"
C.f"{value%:.2f}"
D.f"{value:2f}"
AnswerA

Correct. The format specifier `.2f` is a dot (precision marker) followed by `2` (the number of digits) and the fixed-point type `f`. This tells Python to render `value` as a float rounded to exactly two decimal places, so 3.14159 becomes `3.14`. This is the official way to force a fixed number of digits after the decimal point in f-string formatting.

Why this answer

Uses the correct f-string format specifier `:.2f`, where `f` stands for fixed-point notation and `.2` specifies two decimal places. This is the standard Python syntax for formatting a floating-point number to two decimal places within an f-string.

Exam trap

The Python Institute often tests the distinction between the width specifier (e.g., `:2f`) and the precision specifier (e.g., `:.2f`), so candidates mistakenly choose Option D thinking `:2f` means two decimal places, when it actually sets a minimum field width of 2 characters.

How to eliminate wrong answers

Option B is wrong because `:.2` omits the `f` type specifier, which means Python will apply the general format type (default `g`) and may not produce exactly two decimal places (e.g., it could use scientific notation or drop trailing zeros). Option C is wrong because `%` is not a valid format specifier component; the correct syntax uses a colon `:` after the expression, not a percent sign. Option D is wrong because `:2f` lacks the decimal point before the `2`, so it specifies a minimum width of 2 characters rather than two decimal places, which can lead to incorrect formatting (e.g., `f"{3.14159:2f}"` outputs `"3.141590"` with six decimal places, not two).

218
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.

219
MCQeasy

A developer needs to check if a filename starts with the prefix 'report_'. Which string method should be used?

A.prefix()
B.startswith()
C.starts()
D.beginwith()
AnswerB

startswith() is the correct and idiomatic Python string method for checking whether a string begins with a given prefix. It accepts a single string, a tuple of strings, or optional start and end indices, returning True if the string starts with the specified prefix and False otherwise. Its behavior is case-sensitive, and it is implemented in C for efficiency, making it the standard tool for this common validation task. This is the only method among the options that actually exists and performs the required check.

Why this answer

The `startswith()` method is the correct string method in Python to check if a string begins with a specified prefix. It returns `True` if the string starts with the given substring, otherwise `False`, making it the exact tool for checking if a filename starts with 'report_'.

Exam trap

Python Institute often tests the exact naming of Python string methods, and the trap here is that candidates may confuse `startswith()` with similar-sounding but non-existent methods like `starts()` or `beginwith()`, or incorrectly assume a method like `prefix()` exists based on other programming languages.

How to eliminate wrong answers

Option A is wrong because `prefix()` is not a valid Python string method; no such method exists in the standard library. Option C is wrong because `starts()` is not a valid Python string method; the correct method name is `startswith()`. Option D is wrong because `beginwith()` is not a valid Python string method; Python uses `startswith()` for this purpose, not `beginwith()`.

220
Multi-Selecteasy

Which TWO of the following string methods return a boolean value?

Select 2 answers
A.startswith()
B.capitalize()
C.format()
D.swapcase()
E.isalpha()
AnswersA, E

startswith() is a boolean predicate that returns True exactly when the string's prefix matches the supplied prefix, optionally constraining the check with the start and end index arguments. It never modifies the original string and its only meaningful return values are True and False, making it one of the two methods that answer the question correctly.

Why this answer

The `startswith()` method returns `True` if the string starts with the specified prefix, otherwise `False`. Similarly, `isalpha()` returns `True` if all characters in the string are alphabetic and there is at least one character, otherwise `False`. Both methods explicitly return a boolean value (`True` or `False`), making them correct choices.

Exam trap

The trap here is that candidates often confuse methods that return a new string (like `capitalize()`, `swapcase()`) with methods that return a boolean, because both are called on string objects and appear similar in syntax.

221
MCQmedium

A team wants a `Logger` class that can be used both as `Logger.log('msg')` on the class itself and as `logger.log('msg')` on an instance, with identical behaviour and no access to instance state. Which decorator should be applied to `log`?

A.`@staticmethod`
B.`@classmethod`
C.`@abstractmethod`
D.`@property`
AnswerA

A static method receives no implicit first argument, so `Logger.log('msg')` and `logger.log('msg')` both call the same function with identical arguments and identical results. Since the method does not need instance state, the absence of `self` is not a problem, and there is no unused `cls` parameter to confuse callers. This exactly matches the requirement of identical behaviour from both the class and an instance.

Why this answer

A static method is bound to neither the instance nor the class, so it can be invoked through either the class name or an instance with the same argument list and the same result. Because the logging behaviour does not depend on instance or class state, the missing implicit parameter is not a limitation. A class method would work but needlessly injects the class as an argument, and the other decorators change attribute semantics rather than call binding.

Exam trap

The trap here is choosing a class method because it is callable from both the class and instances, overlooking that it injects an unused class argument the scenario does not need.

222
MCQeasy

A developer wants to import a specific function 'calculate' from a module named 'formulas' without importing the entire module. Which import statement should be used?

A.import formulas
B.import calculate from formulas
C.from formulas import calculate
D.import formulas as f
AnswerC

This is the correct and idiomatic way to import exactly one function from a module. It binds the name `calculate` directly in the current namespace, so you can call `calculate(...)` without a module prefix, and it avoids pulling in the entire `formulas` module as a separate local name. This form also makes the dependency explicit, which improves readability and reduces the risk of accidentally shadowing other names.

Why this answer

The `from module import name` syntax in Python allows you to import a specific function (or other attribute) from a module directly into the current namespace, without importing the entire module. This avoids unnecessary memory usage and keeps the namespace clean by only bringing in the needed `calculate` function.

Exam trap

Python Institute often tests the distinction between importing a module versus importing a specific attribute, and the trap here is that candidates may confuse the invalid `import calculate from formulas` syntax (Option B) with the correct `from formulas import calculate` syntax, or think that `import formulas` (Option A) is sufficient to use the function directly.

How to eliminate wrong answers

Option A is wrong because `import formulas` imports the entire module, requiring the function to be accessed as `formulas.calculate`, not directly as `calculate`. Option B is wrong because `import calculate from formulas` is invalid Python syntax; the correct order is `from formulas import calculate`. Option D is wrong because `import formulas as f` imports the entire module under an alias, still requiring `f.calculate` to call the function, and does not import the function directly.

223
MCQhard

An abstract base class (ABC) defines an abstract method `process()`. Several subclasses implement it. A function accepts any subclass and calls `process()`. This demonstrates which OOP concept?

A.Inheritance.
B.Encapsulation.
C.Method overloading.
D.Polymorphism.
AnswerD

Polymorphism allows objects of different classes that share a common abstract base to be used interchangeably, with the correct override of `pro` invoked dynamically at runtime. Because `pro` is abstract, each concrete subclass must provide its own implementation, and the Python runtime dispatches to the specific version based on the actual object type. This is precisely the concept the question is testing.

Why this answer

Polymorphism allows objects of different subclasses to be treated uniformly through their common interface. When a function accepts any subclass of the ABC and calls `process()`, the correct implementation is resolved at runtime via dynamic dispatch, which is the essence of polymorphism in Python.

Exam trap

Python Institute often tests the distinction between inheritance and polymorphism by presenting a scenario where multiple subclasses override a method, leading candidates to mistakenly select 'inheritance' because they see the class hierarchy, but the key behavior is the polymorphic call, not the inheritance itself.

How to eliminate wrong answers

Option A is wrong because inheritance alone only establishes a parent-child relationship and code reuse; it does not guarantee that the same method call behaves differently across subclasses. Option B is wrong because encapsulation is about bundling data and methods together and restricting direct access to internal state, which is not demonstrated by calling a method on different subclass objects. Option C is wrong because method overloading refers to multiple methods with the same name but different parameters within the same class, which Python does not support natively; the scenario here uses a single method signature overridden in subclasses, not overloading.

224
MCQhard

When should you raise a specific exception class rather than a generic Exception?

A.When different error conditions require different handling.
B.Always raise Exception for simplicity.
C.Specific exceptions cannot be created; only built-in ones can be used.
D.Only when performance is a concern.
AnswerA

Specific exceptions allow callers to catch precisely the conditions they can handle, using except clauses that match the exception type. Without distinct types, you would have to inspect messages or attributes, which is brittle and error-prone. Thus, raising a specific exception class is warranted when different error conditions require different handling, because the exception type itself becomes part of the API contract.

Why this answer

Raising a specific exception class (e.g., ValueError, KeyError, or a custom subclass) allows the caller to catch and handle each error condition differently using separate except blocks. Using a generic Exception forces all errors into a single handler, which can mask distinct failure modes and make debugging harder. This aligns with Python's EAFP (Easier to Ask for Forgiveness than Permission) idiom, where precise exception types enable fine-grained error recovery.

Exam trap

Python Institute often tests the misconception that generic Exception is simpler or sufficient, but the trap is that it forces all errors into one catch-all, which hides the need for distinct handling logic and violates Pythonic best practices for exception granularity.

How to eliminate wrong answers

Option B is wrong because always raising generic Exception violates the principle of exception specificity, making it impossible for callers to distinguish between error types without inspecting the message string, which is fragile and discouraged. Option C is wrong because Python allows creation of custom exception classes by subclassing Exception (or any other built-in exception), enabling domain-specific error handling. Option D is wrong because performance is rarely a concern when choosing exception types; the decision should be based on semantic clarity and handling requirements, not optimization.

Page 2

Page 3 of 6

Page 4

All pages