Courseiva

Certified Associate Python Programmer PCAP (PCAP) — Questions 301–375

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

Page 4

Page 5 of 6

Page 6
301
MCQeasy

A developer is building an IoT application that reads temperature data from a sensor over a TCP socket. The sensor sends data as a stream of bytes encoded in UTF-8, with each reading terminated by a newline character. The developer uses the following code to receive data: ```python import socket s = socket.socket() s.connect(('sensor.local', 5000)) data = s.recv(1024) ``` The variable `data` is a bytes object. The developer needs to convert it to a string to parse the temperature value. Which of the following lines of code should the developer use to correctly obtain the string representation of the received data, assuming the data is valid UTF-8 and may contain non-ASCII characters?

A.data.encode('utf-8')
B.data.decode('utf-8')
C.bytes(data)
D.str(data)
AnswerB

Because data was read as raw bytes from the IoT sensor, decode('utf-8') is the correct method to interpret those bytes as a Unicode string using the UTF-8 codec. This is the inverse of str.encode() and is exactly what bytes objects are designed to do. After decoding, the result is a normal str that can be compared, parsed, or logged as text.

Why this answer

The `recv()` method returns a bytes object. Since the data is valid UTF-8 and may contain non-ASCII characters, the correct way to convert bytes to a string is by calling `data.decode('utf-8')`. This method interprets the byte sequence according to the UTF-8 encoding and returns a Unicode string.

Exam trap

The trap here is confusing `encode()` and `decode()`: candidates often think bytes need to be 'encoded' to a string, but in Python, bytes are decoded to str, and str is encoded to bytes.

How to eliminate wrong answers

Option A is wrong because `data.encode('utf-8')` attempts to encode a bytes object, which raises an `AttributeError` (bytes have no `encode` method); encoding is for strings, not bytes. Option C is wrong because `bytes(data)` creates a copy of the bytes object, not a string, so it does not perform any conversion. Option D is wrong because `str(data)` returns a string representation like `b'...'` (including the `b` prefix and escapes), not the actual decoded text.

302
Multi-Selectmedium

Which TWO of the following are appropriate techniques for logging exception details in Python? (Select exactly 2)

Select 2 answers
A.Using print(e.args)
B.Using traceback.format_exc()
C.Using sys.exc_info()
D.Using raise without argument
E.Using logging.exception() inside except block
AnswersB, E

Calling traceback.format_exc() inside an except block returns a complete, pre-formatted traceback string that includes the exception type, message, and the entire call stack at the point of failure. This string can be directly written to a log file, sent to a monitoring system, or stored for later analysis, making it an appropriate technique for capturing exception details. Unlike print(e.args), it preserves the full execution context needed to diagnose the root cause.

Why this answer

`traceback.format_exc()` returns the full traceback as a string, which can be logged or printed to capture detailed exception context. Option E is correct because `logging.exception()` automatically includes the traceback of the current exception when called inside an `except` block, making it the idiomatic way to log exceptions in Python.

Exam trap

Python Institute often tests the distinction between merely accessing exception data (like `e.args` or `sys.exc_info()`) and actually formatting or logging it properly, so candidates mistakenly think any function that touches exception info qualifies as a 'logging technique'.

303
MCQhard

Consider the following code snippet: 'class A: pass; class B(A): pass; class C(A): pass; class D(B, C): pass'. What is the Method Resolution Order (MRO) for class D according to the C3 linearization algorithm used by Python?

A.D, B, A, C, object
B.D, B, C, A
C.D, B, A, object, C
D.D, B, C, A, object
AnswerD

This is the correct C3 linearization for D(B, C) where both B and C inherit from A. The merge begins with D, then picks B because it is not in any tail; A is skipped next because it appears in the tail of C's linearization, forcing C to be emitted before A. After C is consumed, A and object are safe to append. The result preserves both parent MROs as subsequences and honors both local precedence order (B before C) and monotonicity, yielding D, B, C, A, object.

Why this answer

The C3 linearization algorithm merges the linearizations of D's parents (B and C) with their parent list, respecting the local precedence order and monotonicity. For class D(B, C), the MRO is computed as D + merge(L(B), L(C), [B, C]), where L(B) = B, A, object and L(C) = C, A, object. The merge yields D, B, C, A, object, which is the correct MRO.

Exam trap

Python Institute often tests the misconception that Python uses depth-first left-to-right resolution (like in old-style classes), leading candidates to pick Option A (D, B, A, C, object) instead of the correct C3 linearization result.

How to eliminate wrong answers

Option A is wrong because it incorrectly places A before C, violating the local precedence order where C should appear before A (since D inherits from B then C, and C is a direct parent). Option B is wrong because it omits 'object', which is always the final class in the MRO for new-style classes in Python. Option C is wrong because it places 'object' before C, which breaks monotonicity and the rule that a parent's MRO must be preserved; C must appear before object.

304
MCQmedium

Refer to the exhibit. What is the output of the code?

A.Program
B.Programming
C.Python Programming
D.Python
AnswerB

With s = 'Python Programming', index 7 points to the uppercase 'P' that begins the second word, 'Programming'. A slice of s[7:] has no explicit stop index, so Python extends it to the string's full length, outputting every character from that 'P' through the final 'g'. The result is exactly 'Programming', the complete suffix of the original string.

Why this answer

The code likely uses slicing with a start index to extract 'Programming' from the string 'Python Programming'. For instance, 'Python Programming'[7:] returns the substring starting at index 7 (after 'Python ' which is 7 characters including space) to the end, which is 'Programming'. This operation is a common way to obtain a substring.

Exam trap

Python Institute often tests whether candidates confuse slicing indices with character positions, leading them to miscount and pick 'Program' (7 characters) instead of 'Programming' (11 characters) when extracting from index 7 onward.

How to eliminate wrong answers

Option A is wrong because 'Program' is only the first 7 characters of 'Programming', missing the final 'ming'. Option C is wrong because 'Python Programming' is the original string, not the output of any slicing or method that would extract a substring. Option D is wrong because 'Python' is the first 6 characters, which would require slicing `[:6]`, but the code does not produce that.

305
MCQmedium

What will the above code output?

A.Index out of range
B.The program runs without output.
C.The program crashes with an unhandled IndexError.
D.ValueError is raised.
AnswerA

The statement attempts to access an element using an index that is equal to or greater than the list's length, or a negative index less than -len(list). Python raises IndexError for any out-of-range sequence access, and the active except IndexError block catches this exact exception, printing the string 'Index out of range'. Since the handler successfully intercepts the exception, the program continues normally after the except block, making this the emitted output.

Why this answer

The code attempts to access an index that is outside the valid range of the string. In Python, strings are zero-indexed, so for a string of length n, valid indices are 0 to n-1. Accessing an index equal to or greater than the length raises an IndexError, which is exactly what 'Index out of range' describes.

Exam trap

The PCAP exam often tests the distinction between IndexError and ValueError, trapping candidates who confuse out-of-range indexing with invalid value operations, such as int('abc') which raises ValueError.

How to eliminate wrong answers

Option B is wrong because the code does produce output — specifically, an error message is printed to stderr when the IndexError occurs, so the program does not run silently without output. Option C is wrong because the program does not crash with an unhandled IndexError; Python's default behavior for an unhandled IndexError is to print a traceback and exit, which is not a 'crash' in the sense of a system-level failure, but rather a controlled termination with an error message. Option D is wrong because a ValueError is raised for invalid literal conversions or inappropriate argument types, not for index access beyond the string's length; the specific exception for out-of-range indexing is IndexError.

306
MCQhard

Given the code above, what is printed? Note: each backslash is a single character.

A.21
B.23
C.22
D.24
AnswerB

The string `C:\Users\John\Documents` (written as a raw string) contains 23 characters: `C`, `:`, `\`, `U`, `s`, `e`, `r`, `s`, `\`, `J`, `o`, `h`, `n`, `\`, `D`, `o`, `c`, `u`, `m`, `e`, `n`, `t`, `s`. Because it is a raw string, each backslash is its own character and none of the letters are escaped, so `len()` on this literal returns exactly 23.

Why this answer

The string "C:\\Users\\John\\Documents" uses double backslashes to represent literal backslashes. Each double backslash `\\` is a single backslash character. Counting all characters: C, :, \, U, s, e, r, s, \, J, o, h, n, \, D, o, c, u, m, e, n, t, s = 23 characters.

Thus, the length is 23.

Exam trap

The PCAP exam often tests the misconception that escape sequences like `\n` or `\t` are counted as single characters, when in fact each backslash is a separate character unless the string uses raw notation.

How to eliminate wrong answers

Option A is wrong because 21 would result from miscounting escape sequences as single characters (e.g., treating `\n` as one newline character). Option C is wrong because 22 might come from forgetting to count one of the backslashes or misinterpreting the number of escape sequences. Option D is wrong because 24 would occur if you counted an extra character, perhaps by including an additional quote or misreading the string length.

307
MCQhard

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

308
MCQhard

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

309
Multi-Selectmedium

A developer is validating user input in a Python application. The string variable `input_str` is assigned the value `'Hello World'`. Which TWO of the following conditions evaluate to `True`? (Choose two.)

Select 2 answers
A.input_str.isalpha()
B.input_str.istitle()
C.input_str.isprintable()
D.input_str.isalnum()
E.input_str.isspace()
AnswersB, C

input_str.istitle() returns True exactly when the string is titlecased: each word boundary is followed by an uppercase letter, and all remaining letters in that word are lowercase. For a value like 'Hello World', both words start with an uppercase letter and the rest are lowercase, so the method returns True. This is the precise built-in predicate for checking titlecase, ignoring spaces and punctuation when identifying words.

Why this answer

`istitle()` returns `True` when the string is titlecased, meaning the first character of each word is uppercase and all other characters are lowercase. 'Hello World' has both words starting with an uppercase letter followed by lowercase letters, so it satisfies this condition.

Exam trap

Python often tests the distinction between `istitle()` and `isupper()` or `isalpha()`, trapping candidates who assume 'Hello World' is alphabetic or alphanumeric because they overlook the space character.

310
MCQhard

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

311
MCQhard

A web application receives a byte string b'\xc3\xa9' which represents the character 'é' in UTF-8. The developer wants to convert it to a Python string. Which operation should be used?

A.b'\xc3\xa9'.encode('utf-8')
B.b'\xc3\xa9'.tostring()
C.str(b'\xc3\xa9', 'ascii')
D.b'\xc3\xa9'.decode('utf-8')
AnswerD

This is the correct conversion: bytes.decode('utf-8') interprets the two-byte sequence 0xC3 0xA9 as the UTF-8 encoding of the Unicode code point U+00E9, which is the character 'é'. The decode() method is specifically designed to turn bytes back into a str using a specified codec, making this the exact inverse of 'é'.encode('utf-8'). The result is the Python string 'é'.

Why this answer

The byte string b'\xc3\xa9' is a UTF-8 encoded representation of the character 'é'. To convert it to a Python string, you must decode it using the .decode('utf-8') method, which interprets the bytes according to the UTF-8 encoding and returns a Unicode string.

Exam trap

The PCAP exam often tests the distinction between .encode() and .decode() on bytes vs. strings, trapping candidates who mistakenly use .encode() on bytes or try to decode with an incompatible codec like ASCII.

How to eliminate wrong answers

Option A is wrong because .encode('utf-8') is used to convert a string to bytes, not the reverse; calling it on a bytes object would raise an AttributeError. Option B is wrong because bytes objects do not have a .tostring() method; this is not a valid Python operation. Option C is wrong because str(b'\xc3\xa9', 'ascii') attempts to decode the bytes using ASCII, but the byte values 0xc3 and 0xa9 are outside the ASCII range (0-127), causing a UnicodeDecodeError.

312
MCQmedium

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

313
Multi-Selectmedium

Which THREE of the following string methods can be used to split a string into a list of substrings? (Choose three.)

Select 3 answers
A.splitlines()
B.split()
C.join()
D.rsplit()
E.partition()
AnswersA, B, D

splitlines() splits a string at Unicode line boundaries such as \n, \r\n, \r, \v, \f, and other line separator characters, returning a list of lines without the line terminators unless keepends=True is passed. It does not accept a separator argument and does not split on spaces or tabs, making it ideal for line-oriented data like file contents or multi-line text.

Why this answer

The `splitlines()` method splits a string at line boundaries (like \n, \r\n, or \r) and returns a list of substrings, making it a valid method for splitting a string into a list. It is specifically designed for handling multi-line strings.

Exam trap

The PCAP exam often tests the distinction between methods that return a list (`split`, `rsplit`, `splitlines`) versus those that return a tuple (`partition`, `rpartition`) or a single string (`join`), leading candidates to mistakenly select `partition` or `join`.

314
MCQeasy

A programmer wants to create a package named 'analytics' with subpackages 'statistics' and 'ml'. Which directory structure correctly defines these packages?

A.analytics/, analytics/statistics/ (__init__.py), analytics/ml/ (__init__.py)
B.analytics/ (__init__.py), analytics/statistics/ (__init__.py), analytics/ml/ (__init__.py), analytics/__init__.py (file)
C.analytics/ (__init__.py), analytics/statistics/, analytics/ml/
D.analytics/ (__init__.py), analytics/statistics/ (__init__.py), analytics/ml/ (__init__.py)
AnswerD

This is the canonical package layout: each directory—`analytics`, `statistics`, and `ml`—contains an `__init__.py` file, which marks it as a regular Python package. The `__init__.py` files are executed when the package is imported, and their presence allows the import system to traverse the hierarchy (e.g., `import analytics.ml`). This structure works in both Python 2 and Python 3 and is the required format for a standard (non-namespace) package.

Why this answer

In Python, a directory is recognized as a package only if it contains an `__init__.py` file (even if empty). To create the 'analytics' package with 'statistics' and 'ml' subpackages, each directory must have its own `__init__.py`. Option D correctly places `__init__.py` in all three directories: `analytics/`, `analytics/statistics/`, and `analytics/ml/`.

Exam trap

Python Institute often tests the misconception that only the top-level package needs an `__init__.py` file, or that subdirectories without `__init__.py` are still valid subpackages, leading candidates to pick option C or A.

How to eliminate wrong answers

Option A is wrong because the top-level `analytics/` directory lacks an `__init__.py` file, so Python will not treat it as a package, making subpackage imports fail. Option B is wrong because it redundantly lists `analytics/__init__.py` twice (once as a parenthesized file and once as a separate entry), which is syntactically incorrect and implies a duplicate file; the correct structure requires exactly one `__init__.py` per directory. Option C is wrong because the subdirectories `analytics/statistics/` and `analytics/ml/` do not contain `__init__.py` files, so they are not recognized as Python packages, only as ordinary directories.

315
MCQhard

A developer writes: print('{:,}'.format(1234567)). What is the output?

A.1234567
B.1.234.567
C.1 234 567
D.1,234,567
AnswerD

Using the format specifier {:,} or the equivalent f-string f"{1234567:,}" applies the comma format, which groups digits by thousands from right to left. The integer 1,234,567 is correctly grouped into the three-digit blocks 1, 234, and 567. Python's format mini-language explicitly adds thousands separators when the comma flag is present, so this is the definitive result of formatting the number as described.

Why this answer

The correct output is '1,234,567' because the format specifier '{:,}' uses the comma as a thousands separator in Python's string formatting. When applied to the integer 1234567, it inserts commas every three digits from the right, producing the locale-independent grouping.

Exam trap

The PCAP exam often tests whether candidates know that the comma in '{:,}' is a literal thousands separator, not a placeholder for any separator, and that it does not adapt to locale-specific symbols like periods or spaces.

How to eliminate wrong answers

Option A is wrong because it shows the number without any formatting, ignoring the comma separator specified in the format string. Option B is wrong because it uses periods as thousands separators, which is a European convention not produced by the comma specifier in Python's format() method. Option C is wrong because it uses spaces as thousands separators, which is not what the comma specifier does; spaces would require a different format specifier or locale settings.

316
MCQhard

Refer to the exhibit. What is the output of the last line?

A.{'name': 'John'}
B.AttributeError: 'Employee' object has no attribute '__salary'
C.{'name': 'John', '__salary': 50000}
D.{'name': 'John', '_Employee__salary': 50000}
AnswerD

Name mangling transforms __salary into _Employee__salary at compile time, and this mangled name becomes the actual key in the instance's __dict__. Therefore, when the last line prints ex9myx.__dict__, it outputs {'name': 'John', '_Employee__salary': 50000}. This is exactly how Python implements pseudo-private attributes, and it is the correct and expected output for this code.

Why this answer

Python uses name mangling for attributes starting with double underscores (like `__salary`). When accessed via `vars()`, the mangled name `_Employee__salary` is shown, not the original `__salary`. The `vars()` function returns the `__dict__` of the object, which contains the mangled attribute name.

Exam trap

The PCAP exam often tests the misconception that `__salary` remains as-is in the object's dictionary, when in fact Python's name mangling renames it to `_Employee__salary` at compile time, and `vars()` reveals the mangled form.

How to eliminate wrong answers

Option A is wrong because it omits the mangled `__salary` attribute entirely, but `vars()` returns all instance attributes, including mangled ones. Option B is wrong because `__salary` is not accessed directly; `vars()` retrieves the attribute from the object's `__dict__`, which exists with the mangled name, so no AttributeError occurs. Option C is wrong because Python does not preserve the original `__salary` name in the instance dictionary; it mangles it to `_Employee__salary` to avoid accidental overriding in subclasses.

317
MCQhard

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

318
MCQmedium

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

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

Recording exact installed versions with `pip freeze` captures the precise dependency state, and `pip install -r requirements.txt` reproduces those pinned versions elsewhere. This satisfies the requirement for identical module versions across environments, since unpinned installs would resolve to newer releases.

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

319
Multi-Selecteasy

Which TWO of the following are valid string methods in Python?

Select 2 answers
A.capitalize()
B.rotate()
C.shuffle()
D.swapcase()
E.reverse()
AnswersA, D

capitalize() is a valid string method that creates and returns a new string with the first character converted to uppercase and all remaining characters converted to lowercase. Because strings are immutable, the original string is not modified, and the method call produces a copy. If the first character is not a letter (e.g., a digit or symbol), it remains unchanged while the rest of the string is lowercased.

Why this answer

`capitalize()` is a built-in string method in Python that returns a copy of the string with its first character capitalized and the rest lowercased. It is part of the standard string methods available for all string objects in Python.

Exam trap

Python Institute often tests the candidate's understanding of string immutability versus list mutability, leading candidates to mistakenly assume that methods like `reverse()` or `shuffle()` apply to strings because they seem intuitive for sequence manipulation.

320
MCQeasy

Refer to the exhibit. What happens when the last line is executed?

A.The attribute 'city' is added dynamically.
B.The __slots__ is ignored because __init__ is defined.
C.A syntax error occurs.
D.An AttributeError is raised.
AnswerD

An AttributeError is raised because the class defines __slots__ = ('name', 'age'), and 'city' is not among the declared slots. Python then prevents the assignment of a new attribute, as instances with __slots__ do not have a __dict__ and cannot create undeclared attributes. This is the correct and intended behavior of __slots__.

Why this answer

When a class defines `__slots__`, it restricts attribute assignment to only those names listed in `__slots__`. Attempting to assign an attribute not in that list (like `city`) raises an `AttributeError` because the instance has no `__dict__` to store dynamic attributes. The `__init__` method does not override this restriction; it simply initializes the allowed slots.

Exam trap

Python Institute often tests the misconception that `__init__` can override `__slots__` or that `__slots__` only applies to class-level attributes, leading candidates to incorrectly choose option B or A.

How to eliminate wrong answers

Option A is wrong because `__slots__` explicitly prevents dynamic addition of attributes not listed in it, so `city` cannot be added dynamically. Option B is wrong because `__slots__` is not ignored when `__init__` is defined; `__init__` only initializes existing slots, it does not bypass the slot restriction. Option C is wrong because no syntax error occurs; the code is syntactically valid, and the error is raised at runtime when the assignment is executed.

321
MCQmedium

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

322
Multi-Selecthard

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

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

This is the definition of a module.

Why this answer

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

Exam trap

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

323
MCQeasy

Refer to the exhibit. The above log shows an unhandled exception that caused the program to crash. The developer wants to handle this exception and log the error without crashing. Which exception type should be caught in the main code to capture this specific error?

A.BaseException
B.ValueError
C.OSError
D.Exception
AnswerB

The log explicitly shows "ValueError: ..." being raised. This is the precise exception type that occurred, so the appropriate handler is except ValueError. It is specific to the problem: a function received an argument of the right type but an inappropriate value. Catching this specific exception allows targeted recovery without swallowing unrelated errors.

Why this answer

The traceback shows that a ValueError was raised. To handle this specific exception, the code should catch ValueError. Catching Exception would also work but is less specific.

Catching BaseException catches system-exit exceptions. OSError is unrelated.

324
MCQhard

Refer to the exhibit. A Python script uses the following code to load the policy. However, it fails with a JSONDecodeError. What is the most likely cause? ```python import json with open('policy.json', 'r') as f: policy = json.load(f) ```

A.The JSON file contains a trailing comma after the last element.
B.The policy variable is used before assignment elsewhere in the script.
C.The file should be opened in binary mode ('rb') instead of text mode.
D.The JSON decoder cannot handle IP addresses in strings.
AnswerA

The correct diagnosis: Python's json.load() is a strict parser that follows RFC 8259, and a trailing comma after the last element is not valid JSON syntax. The file likely contains something like [{"a":1},{"b":2},], which causes the parser to encounter a comma before the closing bracket and raise JSONDecodeError with a message such as 'Expecting value'. No amount of variable handling or file mode changes can repair that malformed structure.

Why this answer

Python's json.load() strictly follows the JSON specification (RFC 7159), which does not allow trailing commas after the last element in an array or object. When the JSON file contains a trailing comma, the decoder raises a JSONDecodeError. This is a common syntax error in hand-written or poorly generated JSON files.

Exam trap

Python Institute often tests the subtle difference between Python's permissive syntax (which allows trailing commas) and the strict JSON specification, leading candidates to incorrectly assume that Python's json module would accept trailing commas.

How to eliminate wrong answers

Option B is wrong because a NameError (not JSONDecodeError) would occur if the variable 'policy' were used before assignment elsewhere; the error in the question is specifically a JSONDecodeError from json.load(). Option C is wrong because json.load() works perfectly with text mode ('r') for JSON files, as JSON is a text-based format; binary mode ('rb') is only needed for non-text data or when using json.loads() on bytes. Option D is wrong because the JSON decoder can handle any valid JSON string, including IP addresses, as they are just strings; there is no special restriction on IP addresses in the JSON specification.

325
MCQmedium

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

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

SavingsAccount redefines the inherited withdraw method with its own penalty logic while keeping the same signature, so Python dispatches to the subclass version at runtime. That substitution of a superclass method implementation is method overriding, not overloading or composition.

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

326
MCQhard

A Python project uses namespace packages spread across multiple directories. The package structure is: project/ and lib/ both contain subdirectories 'mypkg/'. Each has an __init__.py file. When importing 'mypkg', which directory's contents are used?

A.Both directories are merged into a single namespace package.
B.Only the directory that appears first in sys.path is used.
C.An error is raised due to ambiguous import.
D.The last directory in sys.path overrides the previous.
AnswerB

When Python imports a package, the path-based finder scans sys.path from index 0 upward and uses the first directory that contains a matching __init__.py file. That directory is bound to the package name, and the search stops immediately, so later directories are never examined. This deterministic first-match resolution ensures predictable behavior even when multiple copies of the same package exist on the path.

Why this answer

When both directories contain an __init__.py file, they are regular packages, not namespace packages. Python's import system uses the first match in sys.path; it does not merge regular packages. Therefore, only the directory that appears first in sys.path is used, making option B correct.

Exam trap

The trap here is that candidates confuse regular packages (with __init__.py) with namespace packages (without __init__.py), assuming Python merges both regardless, when in fact the presence of __init__.py prevents merging and triggers first-found-wins behavior.

How to eliminate wrong answers

Option A is wrong because namespace packages require directories without __init__.py files; with __init__.py present, each is a regular package and Python does not merge them. Option C is wrong because Python does not raise an error for duplicate package directories; it silently uses the first one found in sys.path. Option D is wrong because Python's import order is first-found-wins, not last-overrides; the last directory in sys.path is never consulted if a match is found earlier.

327
MCQhard

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

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

`rsplit('.', 1)` splits from the right, limiting to one split, so only the final dot separates the extension; indexing `[-1]` returns the trailing segment `'pdf'`. This satisfies the stem's requirement to isolate the extension from `'document.pdf'`, and unlike `split`, it handles filenames containing multiple dots correctly.

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

328
MCQeasy

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

329
MCQhard

A Python application processes user-uploaded files. The requirement is to catch any I/O-related exception while reading the file, but not to catch KeyboardInterrupt or SystemExit. Which exception type should be caught?

A.OSError
B.IOError
C.Exception
D.BaseException
AnswerA

OSError is the correct choice because it is the built-in exception class for all operating-system-related I/O failures—file not found, permission denied, disk full, or invalid file descriptor—and it deliberately excludes system-exiting exceptions like KeyboardInterrupt and SystemExit. Catching OSError lets the application handle upload failures gracefully without masking fatal interpreter or user-interrupt conditions. Since Python 3.3, IOError is an alias of OSError, so OSError is the canonical, forward-compatible name to use.

Why this answer

`OSError` is the base class for all I/O-related exceptions in Python 3, including file reading errors like `FileNotFoundError` and `PermissionError`. It does not catch `KeyboardInterrupt` or `SystemExit`, which inherit directly from `BaseException`, not `Exception`. This makes `OSError` the precise choice for catching I/O errors while allowing program termination signals to propagate.

Exam trap

Python Institute often tests the Python 3 exception hierarchy change where `IOError` is no longer a separate class but an alias of `OSError`, tempting candidates to pick the familiar `IOError` from Python 2 instead of the correct `OSError`.

How to eliminate wrong answers

Option B is wrong because `IOError` was merged into `OSError` in Python 3 and is now an alias; catching `IOError` would work in Python 2 but is deprecated and not the recommended modern approach. Option C is wrong because `Exception` catches all built-in exceptions that inherit from it, including `KeyboardInterrupt` and `SystemExit` (which inherit from `BaseException`), violating the requirement to not catch those. Option D is wrong because `BaseException` is the root of all exceptions and would catch everything, including `KeyboardInterrupt` and `SystemExit`, which is explicitly disallowed.

330
MCQeasy

A module 'config.py' contains a variable 'settings' that is a dictionary. Another script does: from config import settings. Then the script modifies settings['key'] = 'new_value'. What happens?

A.The config module is reloaded and the change is lost.
B.The script gets a copy of the dictionary, so config.settings is unchanged.
C.The change is reflected in config.settings because it is the same object.
D.An error occurs because settings is read-only.
AnswerC

The variable 'settings' in the script and 'config.settings' point to the same dictionary instance in memory. In Python, assignment and import bind names to objects rather than copying the object's data. Since the dictionary is mutable, performing an in-place operation such as settings['new_key'] = value updates the single shared dictionary; no extra mechanism is needed for the change to be visible through config.settings.

Why this answer

Python's import statement binds the name 'settings' in the importing module's namespace to the same dictionary object that exists in config.py. Since dictionaries are mutable, modifying settings['key'] directly mutates the shared object, and the change is visible through config.settings as well.

Exam trap

Python Institute often tests the misconception that from ... import ... creates a copy of the object, when in fact it only binds a reference to the same mutable object in memory.

How to eliminate wrong answers

Option A is wrong because Python does not automatically reload modules after an import; the module is cached in sys.modules and the change persists. Option B is wrong because from config import settings does not create a copy of the dictionary; it creates a reference to the same mutable object, so modifications affect the original. Option D is wrong because dictionary items are not read-only by default; they can be freely assigned unless explicitly protected (e.g., by a custom class or frozen dict).

331
MCQhard

Which of the following best describes the use of the @abstractmethod decorator in Python?

A.It automatically provides a default implementation for a method.
B.It indicates that a method must be overridden in any non-abstract subclass.
C.It creates a method that can be called without an instance.
D.It raises AttributeError if the method is called.
AnswerB

Decorating a method with @abstractmethod registers it in the class's __abstractmethods__ set, and the ABCMeta metaclass enforces that every concrete (non-abstract) subclass must provide an overriding implementation. This enforcement happens at instantiation time: attempting to create an instance of a subclass that leaves any abstract method unimplemented raises TypeError. Thus the decorator expresses a contract that subclasses must fulfill, not a prefix to an automatically inherited implementation.

Why this answer

The @abstractmethod decorator, when used in conjunction with a metaclass like ABC (Abstract Base Class) or by inheriting from ABC, declares a method as abstract. This forces any concrete (non-abstract) subclass to provide an override of that method; otherwise, Python raises a TypeError at instantiation time. Option B correctly captures this mandatory override requirement.

Exam trap

The PCAP exam often tests the distinction between 'must be overridden' and 'can be overridden' — the trap here is that candidates confuse @abstractmethod with a method that simply raises NotImplementedError, which does not enforce overriding at instantiation time.

How to eliminate wrong answers

Option A is wrong because @abstractmethod does not provide any default implementation; it explicitly marks a method as having no implementation in the base class. Option C is wrong because @abstractmethod does not create a static or class method; it is used for instance methods by default, and calling it without an instance would still require the method to be bound to the class, not automatically callable without an instance. Option D is wrong because @abstractmethod does not raise AttributeError when the method is called; instead, if a concrete subclass fails to override it, Python raises a TypeError at instantiation time, not when the method is called.

332
MCQhard

A developer is creating a Python package named 'utils' and wants to control what is imported when a user writes 'from utils import *'. Which file and variable should be defined?

A.Define __all__ as a function that returns the list of modules in '__init__.py'.
B.Define __all__ = ['mod1', 'mod2'] in '__init__.py' of the 'utils' package.
C.Set the __all__ variable in the script that imports the package.
D.Define __all__ as a list of module objects in the main module 'utils.py'.
AnswerB

Placing __all__ = ['mod1', 'mod2'] in the package's __init__.py is the canonical way to declare the package's public interface. When from utils import * is executed, the __init__.py code runs first, and the import system reads the __all__ list from the package's namespace, importing only the listed submodules. This also aids static analysis tools and IDE autocomplete by making the intended exports explicit, and prevents unintended names from leaking out in wildcard imports.

Why this answer

In Python, the `__all__` variable in the `__init__.py` file of a package explicitly defines the list of module names that are exported when a user writes `from utils import *`. This controls the public API of the package and prevents unintended internal modules from being imported.

Exam trap

Python Institute often tests the misconception that `__all__` can be defined in the importing script or as a function, or that it belongs in a separate module file rather than the package's `__init__.py`.

How to eliminate wrong answers

Option A is wrong because `__all__` must be a list of strings (module names), not a function that returns a list; defining it as a function would cause a TypeError when Python tries to iterate over it during the `import *` process. Option C is wrong because `__all__` must be defined inside the package's `__init__.py` (or the module itself), not in the script that imports the package; setting it in the importing script has no effect on what `from utils import *` brings in. Option D is wrong because `__all__` should be defined in the `__init__.py` file of the package, not in a separate `utils.py` main module; the package's `__init__.py` is the file Python reads when the package is imported, and `__all__` there controls the star import behavior.

333
MCQeasy

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

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

Subclasses overriding `calculate_pay()` let each employee type supply its own formula, so hourly pay computes hours × rate while salaried returns the fixed salary. This satisfies the stem's requirement to model distinct employee types sharing one interface, since Python dispatches the overridden method polymorphically at runtime based on the instance's actual class.

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

334
MCQmedium

A class 'Point' is defined with __slots__ = ['x', 'y']. A developer creates an instance p = Point() and tries to set p.z = 10. What happens?

A.The assignment is silently ignored
B.Python issues a warning and adds the attribute
C.The attribute 'z' is added dynamically
D.AttributeError is raised
AnswerD

AttributeError is raised is correct because when a class defines __slots__ without including '__dict__', instances are not given a dictionary for arbitrary attributes. The assignment a.z = ... invokes the instance's __setattr__ method, which finds no descriptor for 'z' and no __dict__ in which to store it, so Python raises AttributeError: 'Point' object has no attribute 'z'. This is a deliberate design choice: slots save memory and enforce a fixed attribute schema by rejecting any attribute not explicitly listed.

Why this answer

When a class defines `__slots__`, it restricts attribute assignment to only those names listed in the tuple. Attempting to assign an attribute not in `__slots__` raises an `AttributeError`. This is a deliberate memory optimization that prevents the creation of a per-instance `__dict__`, so dynamic attributes are disallowed.

Exam trap

Python Institute often tests the misconception that `__slots__` only provides a hint or that attributes can still be added dynamically, when in fact it strictly forbids any attribute not listed in `__slots__`.

How to eliminate wrong answers

Option A is wrong because the assignment is not silently ignored; Python actively raises an exception. Option B is wrong because Python does not issue a warning and add the attribute; it strictly enforces the slot restriction with an error. Option C is wrong because `__slots__` prevents dynamic attribute addition; the attribute 'z' is not added under any circumstances.

335
MCQmedium

Refer to the exhibit. If /var/data/in.csv does not exist, what exception is raised?

A.configparser.NoSectionError
B.PermissionError
C.IndexError
D.FileNotFoundError
AnswerD

Opening /var/data/in.csv with the built-in open() function raises FileNotFoundError when the path does not exist, satisfying the stem's missing-file constraint. This OSError subclass carries errno ENOENT and is raised before any read occurs, so no other exception type applies here.

Why this answer

When a file does not exist and you attempt to open it for reading using the built-in `open()` function, Python raises a `FileNotFoundError`. This is a subclass of `OSError` and is the standard exception for missing files in Python 3. The question explicitly states that `/var/data/in.csv` does not exist, so the correct exception is `FileNotFoundError`.

Exam trap

A common trap in Python exams is confusing FileNotFoundError with PermissionError. When a file does not exist, Python raises FileNotFoundError, not PermissionError. Always verify the file's existence before attempting to open it.

How to eliminate wrong answers

Option A is wrong because `configparser.NoSectionError` is raised by the `configparser` module when a requested section is not found in a configuration file, not when a file is missing. Option B is wrong because `PermissionError` is raised when the file exists but the user lacks the necessary permissions to read or write it, not when the file is absent. Option C is wrong because `IndexError` is raised when a sequence subscript is out of range, such as accessing a list element with an invalid index, and has no relation to file I/O operations.

336
MCQhard

Given the string 'Python', what is the result of 'Python'[::-1]?

A.'nohtyp'
B.'NOHYP'
C.'nohtyP'
D.'Python'
AnswerC

This is exactly the output of the slice `'Python'[::-1]`, which steps through the string from the last character to the first with a step of -1. Python's slicing mechanism creates a new string by copying the characters in reverse order while preserving each character's case and position relative to the others. Because the original string begins with an uppercase 'P', that 'P' appears at the final index, yielding 'nohtyP'.

Why this answer

The slice notation [::-1] creates a reversed copy of the string by using a step of -1, which traverses the sequence from the end to the beginning. Since strings in Python are immutable sequences of Unicode characters, this operation returns a new string with the characters in reverse order, preserving the original case of each character.

Exam trap

Python Institute often tests whether candidates understand that [::-1] reverses the sequence without altering case, so the trap is assuming the step of -1 also applies case transformations like lowercasing or uppercasing.

How to eliminate wrong answers

Option A is wrong because it incorrectly lowercases the entire string; the slice [::-1] does not change the case of characters, it only reverses their order. Option B is wrong because it uppercases the entire string, which is not an effect of the slice operation. Option D is wrong because it returns the original string unchanged, but [::-1] always produces a reversed copy, not the original.

337
MCQhard

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

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

Inside a package, sub2 is a sibling of sub1, so a bare import searches the top-level namespace and fails. Python 3 requires an explicit relative import, from .sub2 import helper, to resolve the sibling subpackage within mypackage.

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

338
MCQeasy

A developer defines a class 'Car' with an attribute 'wheels = 4'. They create two instances: car1 = Car() and car2 = Car(). Then they set car1.wheels = 3. What is the value of car2.wheels?

A.4
B.3
C.AttributeError
D.None
AnswerA

Since car2 never receives an instance attribute named wheels, Python's attribute lookup falls back to the class attribute defined on Car. At the time car2.wheels is evaluated, that class attribute still holds the integer 4, because the assignment car1.wheels = 3 only adds an entry to car1's __dict__, leaving the class-level value untouched. Therefore the correct result is 4, not 3, None, or an error.

Why this answer

In Python, setting an attribute directly on an instance (car1.wheels = 3) creates an instance attribute that shadows the class attribute for that specific instance only. The class attribute 'wheels = 4' remains unchanged and is still accessible via car2.wheels, which has not been overridden. Therefore, car2.wheels retains the class-level value of 4.

Exam trap

Python Institute often tests the distinction between class attributes and instance attributes, trapping candidates who mistakenly think that modifying an instance attribute propagates to other instances or that it raises an error.

How to eliminate wrong answers

Option B is wrong because it assumes that modifying an instance attribute on one object affects all instances of the class, which is not true in Python; instance attribute assignments are local to that instance. Option C is wrong because no AttributeError occurs: car2.wheels successfully resolves to the class attribute 'wheels' defined in the Car class. Option D is wrong because car2.wheels is not None; it is explicitly set to 4 at the class level and never reassigned.

339
MCQeasy

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

340
MCQmedium

Consider the following code: class A: x = 1; class B(A): pass; class C(A): x = 2; class D(B, C): pass. What is D.x?

A.AttributeError
B.1
C.2
D.(1, 2) tuple
AnswerC

C's x = 2 is the correct result because attribute lookup walks D.__mro__ in order: D, B, C, A, object. B adds no x attribute, so the first slot that defines x is C, and its value 2 is returned immediately. This is exactly how the C3 linearization resolves the diamond: the direct base class C is visited before the shared ancestor A. The number 2 therefore comes from the local precedence of C over A in the class definition D(B, C).

Why this answer

Python's method resolution order (MRO) for class D, which uses multiple inheritance, follows the C3 linearization algorithm. The MRO for D is D, B, C, A, and since C defines x = 2, that attribute overrides the x = 1 from A in the inheritance chain, so D.x resolves to 2.

Exam trap

Python Institute often tests the misconception that Python's multiple inheritance simply merges attributes from all parent classes, leading candidates to expect a tuple or an error, rather than applying the C3 linearization to determine a single overriding value.

How to eliminate wrong answers

Option A is wrong because D inherits from B and C, which both ultimately inherit from A, so x is defined in the hierarchy and no AttributeError occurs. Option B is wrong because although A defines x = 1, the MRO prioritizes C's definition of x = 2 over A's, so D.x is not 1. Option D is wrong because attribute lookup in Python does not return a tuple of all inherited values; it returns a single value from the first class in the MRO that defines the attribute.

341
Multi-Selecteasy

Which TWO of the following expressions evaluate to `True`? (Select exactly two.)

Select 2 answers
A.'ab' in 'abc'
B.'x' in 'abc'
C.'ab' not in 'abc'
D.'a' in 'abc'
E.'abc' in 'ab'
AnswersA, D

Python's `in` operator for strings performs a substring containment test, checking whether the left operand appears as a contiguous sequence within the right operand. In 'abc', the two-character sequence 'ab' is present at indices 0 and 1, so the expression evaluates to True. This is exact, character-by-character matching with no wildcard or fuzzy semantics.

Why this answer

The `in` operator checks if the substring 'ab' appears anywhere within the string 'abc'. Since 'abc' contains the consecutive characters 'a' followed by 'b', the expression evaluates to True.

Exam trap

The trap here is that candidates may confuse the `in` operator with checking individual characters in any order, or mistakenly think that a longer substring can be found in a shorter string, leading them to select option E.

342
MCQeasy

Which string method can be used to check if a string contains only digits?

A.str.isdigit()
B.str.isalnum()
C.str.isdecimal()
D.str.isnumeric()
AnswerA

str.isdigit() returns True only when the string is non-empty and every character has the Unicode Numeric_Type of Digit or Decimal, which includes ASCII '0'-'9', non-Arabic decimal digits, and compatibility superscripts such as '²'. This is the broadest check that still excludes letters, punctuation, and numeric fractions, so it is the correct method when the requirement is to verify that a string contains only digits.

Why this answer

The `str.isdigit()` method returns `True` if all characters in the string are digits (0-9) and the string is non-empty. This is the most direct and commonly used method for checking numeric-only strings in Python, as it specifically tests for digit characters without including other numeric forms like fractions or Roman numerals.

Exam trap

Python Institute often tests the subtle differences between `isdigit()`, `isdecimal()`, and `isnumeric()` by presenting a string with a Unicode digit (e.g., '²' or '½') and expecting candidates to know that `isdigit()` returns `True` for superscripts but `isdecimal()` does not, causing confusion about which method truly checks 'only digits'.

How to eliminate wrong answers

Option B is wrong because `str.isalnum()` returns `True` if all characters are alphanumeric (letters or digits), so it would incorrectly accept strings containing letters. Option C is wrong because `str.isdecimal()` only returns `True` for decimal digits (0-9 in most scripts) but may fail for some Unicode digits like superscripts, and it is more restrictive than `isdigit()`. Option D is wrong because `str.isnumeric()` returns `True` for any numeric character including fractions, Roman numerals, and other Unicode numeric values, so it is broader than checking only digits.

343
MCQhard

Consider the following code: result = ' '.join(['a', 'b', 'c']) print(repr(result)) What is the output?

A.['a', 'b', 'c']
B."a b c"
C.'a b c'
D.a b c
AnswerC

This is the exact string returned by the join() operation: a single string containing the characters 'a', a space, 'b', another space, and 'c'. In an interactive Python session or when using repr(), the result is shown with single quotes around it to clearly delimit it as a textual string object. The single quotes are part of the representation, not the actual data, and they confirm the value is a str, not a list or other container.

Why this answer

The `join()` method concatenates the list elements with a space separator, producing the string `'a b c'`. The `repr()` function returns a string representation that includes quotes, so the output is `'a b c'` (with single quotes). Option C is correct because it matches the exact output of `print(repr(result))`.

Exam trap

Python Institute often tests the difference between `str()` and `repr()`, and the trap here is that candidates forget `repr()` adds quotes to the string output, leading them to choose the unquoted version (Option D) or the wrong quote style (Option B).

How to eliminate wrong answers

Option A is wrong because it shows the original list `['a', 'b', 'c']`, but the code joins the list into a string, not a list. Option B is wrong because it uses double quotes `"a b c"`, but `repr()` in Python returns a string with single quotes by default (unless the string contains a single quote). Option D is wrong because it shows the string without any quotes `a b c`, but `repr()` always adds quotes to indicate it is a string representation.

344
MCQhard

Refer to the exhibit. A Python script uses re.split with a regex pattern. What is the output?

A.['one two three']
B.['one', 'two', 'three', '']
C.['one', 'two', 'three']
D.['one', ' ', 'two', ' ', 'three']
AnswerC

This is the correct output: r'\s+' matches one or more whitespace characters as a single delimiter, so the spaces before and after words are consumed. With the input 'one two three', each word is separated by exactly one space, and there is no leading/trailing whitespace, yielding exactly three substrings. The regex engine advances past all matching whitespace, so no empty strings appear.

Why this answer

`re.split(r'\s+', 'one two three')` splits the string on one or more whitespace characters (`\s+`). The pattern consumes all contiguous whitespace as a single delimiter, producing a list of the three non-empty substrings: `['one', 'two', 'three']`. No trailing empty string is included because the string does not end with whitespace.

Exam trap

The PCAP exam often tests the distinction between splitting on a single character vs. a regex quantifier like `+`, leading candidates to mistakenly think each space produces a separate list element or that trailing delimiters always produce empty strings.

How to eliminate wrong answers

Option A is wrong because it incorrectly suggests the output is a single-element list containing the original string, which would only happen if the pattern never matched (e.g., using a non-existent delimiter). Option B is wrong because it includes a trailing empty string, which would occur only if the string ended with a delimiter (e.g., `'one two three '`), but the input has no trailing whitespace. Option D is wrong because it treats each individual space character as a separate delimiter, which would happen with a pattern like `r' '` (single space) rather than `r'\s+'` (one or more whitespace).

345
MCQhard

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

346
MCQhard

A data scientist needs to count the occurrences of a substring in a long DNA sequence (e.g., 1 million bases). However, the count must include overlapping occurrences. For example, in 'AAAA', the substring 'AA' appears three times overlapping. The built-in count() method does not count overlapping matches. The scientist needs a function to count overlapping substrings efficiently without using third-party libraries. Which of the following approaches is the most efficient for this task?

A.Use a for loop with slicing and compare: sum(1 for i in range(len(s)-len(sub)+1) if s[i:i+len(sub)] == sub)
B.Use two nested loops to check all possible positions
C.Use re.findall with a positive lookahead: len(re.findall(r'(?=AA)', sequence))
D.Use a while loop with str.find() and increment the start index by 1
AnswerC

The positive lookahead (?=AA) matches the zero-width position where the substring 'AA' begins, without consuming any characters, so the regex engine can find overlapping occurrences at every starting index. re.findall returns one empty-string match for each such position, so len() gives the exact count of overlapping occurrences. This is efficient because the regex engine scans the string once in O(n) time for a literal pattern, with no substring copying or manual index stepping. It is the cleanest solution when overlapping matches must be counted.

Why this answer

`re.findall` with a positive lookahead `(?=AA)` matches overlapping occurrences without consuming characters. The lookahead assertion checks for the substring at each position without advancing the match position, so every overlapping occurrence is found. This is more efficient than manual loops because the underlying regex engine is implemented in C and optimized for pattern matching.

Exam trap

Python Institute often tests the distinction between overlapping and non-overlapping matches, and the trap here is that candidates assume `str.count()` or simple loops are sufficient, not realizing that overlapping matches require a zero-width assertion like lookahead in regex.

How to eliminate wrong answers

Option A is wrong because it uses a Python-level for loop with slicing, which creates a new string object for each slice (O(n*k) memory and time overhead) and is slower than a C-level regex. Option B is wrong because two nested loops would be O(n^2) or worse, which is extremely inefficient for a 1-million-base sequence. Option D is wrong because `str.find()` with incrementing start index by 1 still requires Python-level loop overhead and repeated method calls, and it does not leverage the optimized C implementation of regex.

347
MCQhard

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

348
Multi-Selecteasy

Which TWO of the following string methods return a new string without modifying the original?

Select 2 answers
A.index()
B.replace()
C.strip()
D.find()
E.count()
AnswersB, C

The replace() method takes two substrings and returns a brand-new string in which all non-overlapping occurrences of the first substring have been replaced with the second. Since strings are immutable, the original string is untouched; instead, the method constructs a new string and returns it. This precisely matches the condition of returning a new string.

Why this answer

The `replace()` method returns a new string with all occurrences of a substring replaced by another substring, without altering the original string. Similarly, `strip()` returns a new string with leading and trailing whitespace (or specified characters) removed, leaving the original unchanged. Both methods are non-mutating because strings in Python are immutable.

Exam trap

Python Institute often tests the distinction between methods that return a new string (like `replace()` and `strip()`) versus those that return an index or count (like `index()`, `find()`, and `count()`), trapping candidates who confuse 'returning a value' with 'returning a new string'.

349
Multi-Selectmedium

Which TWO of the following are valid ways to read a file line by line without loading the entire file into memory?

Select 2 answers
A.lines = list(f)
B.for line in f:
C.contents = f.read().split('\n')
D.while True: line = f.readline(); if not line: break
E.lines = f.readlines()
AnswersB, D

This is the canonical line-by-line iteration in Python. The file object is an iterator that yields one line at a time, reading from disk lazily as the loop advances, so only one line resides in memory at a time. This is memory-efficient and the recommended way to process text files sequentially.

Why this answer

Iterating directly over a file object with `for line in f:` reads one line at a time from the file's internal buffer, never loading the entire file into memory. This is the idiomatic and memory-efficient way to process large files line by line in Python.

Exam trap

Python Institute often tests the distinction between methods that load the entire file into memory (like `readlines()`, `read().split()`, and `list(f)`) versus the iterator protocol that processes lines lazily, and candidates frequently confuse `list(f)` as being lazy because it uses the file object.

350
MCQmedium

What is the output of the following code? s = 'Hello'; print(s.find('l'))

A.1
B.2
C.0
D.3
AnswerB

Option 2 is correct: the string 'hello' has the character positions h(0), e(1), l(2), l(3), and o(4). When str.index('l') is called, Python scans the string left-to-right and returns the smallest index where the substring 'l' occurs, which is 2. Therefore the code prints the integer 2.

Why this answer

The `str.find()` method returns the lowest index of the first occurrence of the substring. In the string 'Hello', the character 'l' first appears at index 2 (0-based indexing: H=0, e=1, l=2). Therefore, `s.find('l')` returns 2, making option B correct.

Exam trap

PCAP often tests the distinction between 0-based and 1-based indexing, and the fact that `find()` returns the first occurrence, not the last or any subsequent one.

How to eliminate wrong answers

Option A is wrong because it assumes 1-based indexing, but Python uses 0-based indexing, so the first 'l' is at index 2, not 1. Option C is wrong because index 0 corresponds to 'H', not 'l'. Option D is wrong because index 3 corresponds to the second 'l' in 'Hello', but `find()` returns the first occurrence, which is at index 2.

351
MCQhard

Refer to the exhibit. What is the root cause of the error?

A.The attribute 'age' is not defined in the class or instance.
B.The __init__ method was not called.
C.The attribute 'age' is private.
D.The attribute 'age' is a class attribute but not initialized.
AnswerA

The attribute lookup for 'age' fails because it was never set on the instance or the class. When an object attribute is accessed, Python first checks the instance's __dict__, then the class and its base classes; since neither 'self.age' in __init__ nor a class-level 'age' exists, AttributeError is raised. The instance only has 'name' assigned, so any other attribute name, including 'age', is undefined.

Why this answer

The error 'AttributeError: 'ClassName' object has no attribute 'age'' occurs when code attempts to access an instance attribute that has never been defined. In Python, attributes must be assigned (e.g., in __init__ or directly on the instance) before they can be read; simply declaring a class-level variable named 'age' would not cause this error, but if no assignment exists, the attribute is missing.

Exam trap

The PCAP exam often tests the distinction between a missing attribute (AttributeError) and an uninitialized class attribute (which would not raise an error), tempting candidates to pick Option D when the real issue is that the attribute was never defined at all.

How to eliminate wrong answers

Option B is wrong because even if __init__ is never called, the error is not about the method being uncalled—it is about the attribute 'age' never being assigned anywhere. Option C is wrong because Python does not have true private attributes; name mangling (double underscore prefix) would change the attribute name to _ClassName__age, but the error message would still reference the mangled name, not 'age'. Option D is wrong because a class attribute that is not initialized would still exist (defaulting to the name 'age' in the class dict) and would not cause an AttributeError; the error only occurs when the attribute is completely absent from both the instance and the class.

352
MCQmedium

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

353
MCQmedium

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

354
Multi-Selecthard

Which THREE of the following expressions return the string "Python"? (Choose three.)

Select 3 answers
A."Python"[::2]
B."Python"[:]
C."Python"[0:6:1]
D."Python"[0:6]
E."Python"[:-1]
AnswersB, C, D

The expression `"Python"[:]` is a full slice: both the start and stop indices are omitted, and the step defaults to 1. With these defaults, Python interprets the slice as starting at index 0 and stopping at the length of the sequence, thereby including every character in order. This idiom is commonly used to create a copy of a sequence; here it returns a new string object containing exactly the same characters as the original: `'Python'`.

Why this answer

Slicing the entire string with '[:]' returns a copy of the full string, which is 'Python'. This is a common idiom for copying a sequence in Python.

Exam trap

A common trap is the misconception that a slice with a step other than 1 (e.g., '::2') returns the full string, or that negative step or omitted stop index produces the same result as a full slice.

355
Multi-Selecteasy

Which TWO of the following are immutable in Python?

Select 2 answers
A.Set
B.Tuple
C.String
D.Dictionary
E.List
AnswersB, C

Tuples are immutable sequences; once created, their contents cannot be changed, added, or removed. Although tuples can contain mutable objects (like a list), the tuple's own structure and element references are fixed, making it hashable only if all elements are hashable. This immutability allows tuples to serve as dictionary keys when they contain only immutable elements.

Why this answer

Tuple (B) is immutable because once created, its elements cannot be added, removed, or changed. This is enforced by Python's internal structure: tuples are stored as a fixed-length array of PyObject pointers, and any attempt to modify them raises a TypeError.

Exam trap

Python Institute often tests the misconception that strings are mutable because they support indexing and slicing, but candidates forget that any operation that appears to change a string actually returns a new string object, leaving the original unchanged.

356
MCQhard

Consider the following code snippet: try: x = int(input()) y = 10 / x print(y) except ZeroDivisionError: print('Division by zero') except ValueError: print('Invalid integer') If the user enters '0', what is the output?

A.No output
B.Both 'Invalid integer' and 'Division by zero'
C.Division by zero
D.Invalid integer
AnswerC

When the user enters '0', int('0') returns 0 without error, so the try block proceeds to evaluate 10 / 0. This expression raises ZeroDivisionError, and Python matches it to the except ZeroDivisionError clause, causing 'Division by zero' to be printed. The output is exactly that message, demonstrating that an exception raised by an arithmetic operation is handled by its specific handler.

Why this answer

When the user enters '0', the input is successfully converted to the integer 0 by int(), so no ValueError occurs. Then 10 / 0 raises a ZeroDivisionError, which is caught by the except ZeroDivisionError block, printing 'Division by zero'. Option C is correct because the code never reaches the ValueError handler.

Exam trap

Python Institute often tests the order of exception handling and the fact that int('0') succeeds, leading candidates to mistakenly think a ValueError occurs or that both exceptions could fire.

How to eliminate wrong answers

Option A is wrong because the ZeroDivisionError is raised and caught, so there is output ('Division by zero'), not no output. Option B is wrong because only one exception occurs (ZeroDivisionError), not both; the ValueError handler is only triggered if int() fails, which it does not here. Option D is wrong because 'Invalid integer' would only print if the input could not be converted to an integer (e.g., entering 'abc'), but '0' is a valid integer string.

357
MCQeasy

A module 'shapes.py' defines several classes: Circle, Square, Triangle. The developer wants to allow users to import only Circle and Square when they use 'from shapes import *'. Which mechanism should be used?

A.Prefix the Triangle class with an underscore to make it private.
B.Use the import_explicit function.
C.Create an __init__.py file in the same directory.
D.Define a list variable named __all__ containing the string names 'Circle' and 'Square'.
AnswerD

Setting __all__ = ['Circle', 'Square'] at the top level of shapes.py explicitly whitelists those two classes for wildcard imports; any other public name, such as Triangle, will be ignored by from shapes import *. This is the canonical Python mechanism for declaring a module's public API, and it is also honored by documentation generators and linters, making the module's intended exports unambiguous.

Why this answer

The `__all__` variable in a module explicitly controls which names are exported when a client uses `from shapes import *`. By setting `__all__ = ['Circle', 'Square']`, only those two classes are imported, while `Triangle` is excluded. This is the standard Python mechanism for restricting wildcard imports.

Exam trap

Python Institute often tests the misconception that an underscore prefix makes a name truly private or that an `__init__.py` file alone controls wildcard imports from a single module, leading candidates to choose A or C instead of the correct `__all__` mechanism.

How to eliminate wrong answers

Option A is wrong because prefixing a name with an underscore (e.g., `_Triangle`) only signals that it is intended for internal use; it does not prevent `from shapes import *` from importing it — Python does not enforce privacy. Option B is wrong because there is no built-in function named `import_explicit` in Python; this is a fabricated term. Option C is wrong because an `__init__.py` file is used to mark a directory as a package and can define its own `__all__`, but it does not control imports from a single module file like `shapes.py`; the question specifies a module, not a package.

358
MCQhard

A class `ServerConfig` has a class attribute `port = 8080`. After deployment, a developer runs `ServerConfig.port = 9090` in one module, and unexpectedly all existing instances now use port 9090. What concept explains this behavior?

A.Instance attributes always override class attributes.
B.The attribute is immutable.
C.Class attributes are shared among all instances of a class.
D.Python uses copy-on-write for attribute access.
AnswerC

Class attributes live on the class object itself, so every instance resolves `port` through the class unless it defines its own. Rebinding `ServerConfig.port = 9090` mutates that single shared slot, which is why all existing instances immediately report 9090 without any instance-level assignment.

Why this answer

Class attributes in Python are shared across all instances of a class. When you modify `ServerConfig.port` on the class itself, every instance that accesses `port` via the class (or via an instance that hasn't overridden it) sees the new value. This is fundamental to Python's attribute lookup mechanism: instance attributes shadow class attributes, but if no instance attribute exists, the class attribute is used.

Exam trap

Python Institute often tests the distinction between modifying a class attribute via the class vs. modifying it via an instance; the trap is that candidates think assigning to `instance.port` changes the class attribute, but it actually creates a new instance attribute that shadows the class attribute.

How to eliminate wrong answers

Option A is wrong because instance attributes only override class attributes when they are explicitly set on the instance; they do not cause class-level changes to propagate. Option B is wrong because the attribute `port` is an integer, which is immutable, but immutability does not affect sharing or rebinding of the attribute on the class. Option D is wrong because Python does not use copy-on-write for attribute access; it uses a dynamic lookup chain (instance → class → parent classes) and assignment always modifies the target directly.

359
MCQeasy

A class has a method that does not access any instance or class data. What decorator should be used to define it as a utility method that can be called on the class itself without requiring an instance?

A.@property
B.@staticmethod
C.@abstractmethod
D.@classmethod
AnswerB

@staticmethod is correct because it explicitly declares that the method does not receive the implicit first argument—neither `self` nor `cls`—so it can be defined and called without any reference to instance or class state. It is still stored on the class for organizational purposes, but behaves essentially like a plain function in terms of argument binding. This makes it the exact decorator for a method that accesses no instance or class data.

Why this answer

A @staticmethod decorator defines a method that does not receive an implicit first argument (self or cls). It can be called on the class itself without creating an instance, making it suitable for utility functions that do not access instance or class data. This matches the requirement.

Exam trap

PCAP often tests the confusion between @staticmethod and @classmethod, where candidates might think @classmethod is for utility methods, but it actually receives the class as an argument.

How to eliminate wrong answers

Option A is wrong because @property is used to define a method as a getter for an attribute, allowing it to be accessed like an attribute, but it still requires an instance and typically accesses instance data. Option C is wrong because @abstractmethod is used to declare abstract methods in abstract base classes, which must be overridden by subclasses; it does not make a method callable on the class without an instance. Option D is wrong because @classmethod defines a method that receives the class as the first argument (cls), and while it can be called on the class, it is intended for methods that need to access or modify class state, not for utility methods that do not access any data.

360
MCQeasy

What will be the output of the following code? try: print(1/0) except: print('error') else: print('no error') finally: print('done')

A.no error\ndone
B.error\nno error\ndone
C.done
D.error\ndone
AnswerD

This is the correct output because the try block raises an exception that is caught by the except handler, which immediately prints 'error'. The else clause, which would print 'no error', is skipped because an exception was raised. The finally clause then unconditionally executes and prints 'done', producing exactly two lines: 'error' and 'done' in that order.

Why this answer

The code raises a ZeroDivisionError when attempting 1/0, which is caught by the bare except clause, printing 'error'. The else clause is skipped because an exception occurred. The finally clause always executes, printing 'done'.

Thus the output is 'error' followed by 'done'.

Exam trap

Python Institute often tests the order of execution in try/except/else/finally, specifically that the else block is skipped when an exception occurs, and that finally always runs, leading candidates to mistakenly include 'no error' or omit 'error'.

How to eliminate wrong answers

Option A is wrong because it suggests the except block was skipped and the else block ran, which would only happen if no exception occurred; but 1/0 raises an exception. Option B is wrong because it includes 'no error' from the else block, which is never executed when an exception is caught. Option C is wrong because it omits 'error', implying the except block did not execute, but the exception is indeed caught and handled.

361
Multi-Selectmedium

Which TWO of the following string methods modify the string in place? (Note: Python strings are immutable.)

Select 2 answers
A.str.join()
B.str.lower()
C.str.upper()
D.str.replace()
E.str.strip()
AnswersB, C

str.lower() returns a new string with all characters lowercased; the original string remains unchanged.

Why this answer

None of the listed string methods modify the string in place because Python strings are immutable. All string methods return a new string rather than altering the original. Therefore, there are no correct options for this question.

Exam trap

The question is designed to test the understanding that strings are immutable. The trap is that candidates may incorrectly believe that methods like replace() or strip() modify the string in place, but in fact no string method modifies the original string.

362
MCQeasy

Which of the following is the correct way to open a file for writing in text mode, ensuring that if the file already exists it will be overwritten?

A.open('file.txt', 'x')
B.open('file.txt', 'w')
C.open('file.txt', 'r+')
D.open('file.txt', 'a')
AnswerB

The 'w' mode opens the file for writing and truncates it to zero bytes if it exists, or creates a new file if it does not. This makes it the standard choice for write operations that should replace the entire contents of the file. It is the correct mode here because it permits immediate writing to the file with the expectation that prior content will be discarded.

Why this answer

The 'w' mode opens the file for writing in text mode and truncates the file to zero length if it exists, or creates a new file if it does not. This ensures any existing content is overwritten, which matches the requirement.

Exam trap

Python Institute often tests the distinction between 'w' and 'x' modes, where candidates mistakenly choose 'x' thinking it creates a new file for writing, but forget that 'x' raises an error if the file already exists, failing the overwrite requirement.

How to eliminate wrong answers

Option A is wrong because 'x' mode opens the file for exclusive creation, raising a FileExistsError if the file already exists, rather than overwriting it. Option C is wrong because 'r+' mode opens the file for both reading and writing without truncating it, so existing content is preserved and not overwritten unless explicitly written over. Option D is wrong because 'a' mode opens the file for appending, writing data at the end of the file without truncating or overwriting existing content.

363
MCQeasy

A developer needs to write binary data to a file. Which file mode should be used to open the file for writing in binary mode without truncating it if it already exists?

A.'wb'
B.'rb'
C.'ab'
D.'wb+'
AnswerC

'ab' opens a file for binary append: if the file exists, the file pointer is positioned at the end so all writes are appended after existing data, and the original content is never truncated. If the file does not exist, a new empty file is created automatically. This makes 'ab' the appropriate choice when writing binary data without destroying prior content.

Why this answer

('ab') is correct because the 'a' mode opens the file for appending, which writes data at the end without truncating the existing content, and adding 'b' specifies binary mode. This allows binary data to be written to a file that already exists without losing its current contents.

Exam trap

Python Institute often tests the distinction between 'w' (truncate) and 'a' (append) modes, trapping candidates who assume 'wb' is the only way to write binary data without considering preservation of existing content.

How to eliminate wrong answers

Option A ('wb') is wrong because 'w' mode truncates the file to zero length upon opening, destroying any existing data. Option B ('rb') is wrong because 'r' mode opens the file for reading only, not writing. Option D ('wb+') is wrong because 'w+' mode also truncates the file upon opening, even though it allows both reading and writing.

364
MCQmedium

A developer is troubleshooting an ImportError: 'No module named 'config''. The config module is located in a subdirectory 'utils' relative to the script. The script's current working directory is the parent of 'utils'. Which of the following lines, added to the script, will resolve the issue?

A.sys.path.append('utils/config.py')
B.sys.path.append('utils')
C.sys.path = os.path.join(sys.path, 'utils')
D.os.chdir('utils')
AnswerB

This is the correct fix because sys.path is a list of directories Python searches when resolving import statements. Appending 'utils' adds that directory to the end of the list, making any Python module or package inside it visible to the import system. Since the target module lives directly in utils, adding this directory allows 'import config' or a similarly named module to be found.

Why this answer

The ImportError occurs because Python's module search path (sys.path) does not include the 'utils' subdirectory. Adding 'utils' to sys.path via sys.path.append('utils') tells Python to look inside that directory for modules, resolving the import. Option B is correct because it extends the search path to include the directory containing the config module, without altering the script's working directory or incorrectly appending a file path.

Exam trap

Python Institute often tests the distinction between modifying sys.path with a directory versus a file path, and the trap here is that candidates mistakenly think appending the full file path (option A) or using os.path.join on a list (option C) will work, when only a directory path appended to the list is correct.

How to eliminate wrong answers

Option A is wrong because sys.path expects directory paths, not file paths; appending 'utils/config.py' would cause Python to look for a directory named 'utils/config.py', which does not exist. Option C is wrong because sys.path is a list, not a string, so os.path.join(sys.path, 'utils') will raise a TypeError due to mixing a list with a string. Option D is wrong because os.chdir('utils') changes the current working directory to 'utils', but the script's import statement still looks for 'config' relative to the original working directory; moreover, changing the working directory can break relative file operations elsewhere in the script.

365
Multi-Selecthard

Which THREE are valid escape sequences in Python strings?

Select 3 answers
A.\n
B.\q
C.\\
D.\t
E.\z
AnswersA, C, D

In Python string literals, the backslash introduces an escape sequence, and \n specifically represents the line feed character (ASCII 10), which advances the cursor to the next line. This is one of the most commonly used escapes for creating multiline output or separating lines in text. Although written as two characters in source code, \n is stored as a single character in the resulting string, making it a single indexable element.

Why this answer

\n is a standard escape sequence in Python that represents a newline character (ASCII LF, 0x0A). It is defined in the Python language specification and is commonly used to insert line breaks in string literals.

Exam trap

Python Institute often tests the distinction between valid escape sequences (like \n, \\, \t) and invalid ones (like \q, \z) that beginners might assume exist because they see other backslash combinations in contexts like regex or shell scripting.

366
Multi-Selectmedium

Which TWO statements about method overriding in Python are correct?

Select 2 answers
A.The overriding method can call the parent method using super()
B.The overriding method must have the same name
C.The overriding method requires explicit use of the @override decorator
D.The overriding method must have the exact same parameter list
E.Overriding is resolved at compile time
AnswersA, B

In a subclass, super() returns a proxy bound to the parent classes in the method resolution order, allowing the overriding method to explicitly invoke the version it replaced. Calling super().method(*args) inside the override is idiomatic when you want to extend, rather than completely replace, the inherited behavior. This capability does not make super() mandatory; a subclass may fully override a method without calling its parent at all.

Why this answer

The overriding method can call the parent class's version of the method using the built-in `super()` function, which returns a proxy object that delegates method calls to the parent class. This is a fundamental feature of Python's inheritance mechanism, allowing the child method to extend or modify the parent's behavior while still invoking it.

Exam trap

Python Institute often tests the misconception that Python enforces strict method signatures or requires an `@override` decorator, leading candidates to select options D or C, when in fact Python's dynamic nature allows flexible overriding without compile-time checks.

367
Multi-Selectmedium

Which THREE of the following are valid string methods in Python? (Choose three.)

Select 3 answers
A..capitalize()
B..lower()
C..uppercase()
D..titlecase()
E..swapcase()
AnswersA, B, E

.capitalize() is a built-in string method that capitalizes the first character and lowercases the rest.

Why this answer

All three options A, B, and E are valid Python string methods. .capitalize() returns a copy of the string with its first character capitalized and the rest lowercased. .lower() returns a copy of the string with all characters converted to lowercase. .swapcase() returns a copy of the string with uppercase characters converted to lowercase and vice versa. Options C and D are incorrect because .uppercase() and .titlecase() are not valid Python string methods; the correct methods are .upper() and .title(). Although the question asks to choose two, note that .swapcase() is also a valid method, making three correct options.

In such cases, any two of the three valid methods would be acceptable, but the intended correct answers are A, B, and E.

Exam trap

Python Institute tests exact method names. The trap is that .swapcase() is a valid method, so candidates may incorrectly exclude it if they think only two are valid. Additionally, .uppercase() and .titlecase() are common confusions with the real methods .upper() and .title().

368
MCQeasy

What is the result of the expression 'Hello'[1:3]?

A.'el'
B.'lo'
C.'He'
D.'ell'
AnswerA

Python slicing uses a half-open interval: the start index is included, but the stop index is excluded. In 'hello', the indices are h=0, e=1, l=2, l=3, o=4, so slice [1:3] selects index 1 ('e') and index 2 ('l'), producing 'el'. The character at index 3 is not part of the result because the stop boundary is exclusive.

Why this answer

In Python, string slicing uses the syntax `string[start:stop]`, where `start` is inclusive and `stop` is exclusive. For `'Hello'[1:3]`, the indices are: index 1 = 'e', index 2 = 'l', and index 3 is not included, so the slice returns 'el'. This is a fundamental string slicing behavior defined in Python's sequence protocol.

Exam trap

Python Institute often tests the off-by-one error in slice stop indices, where candidates mistakenly think the stop index is inclusive and select 'ell' (option D) instead of the correct 'el'.

How to eliminate wrong answers

Option B is wrong because 'lo' would result from slicing `[3:5]` (indices 3 and 4), not `[1:3]`. Option C is wrong because 'He' would result from slicing `[0:2]` (indices 0 and 1), not `[1:3]`. Option D is wrong because 'ell' would result from slicing `[1:4]` (indices 1, 2, and 3), but the stop index 3 excludes index 3, so only two characters are taken.

369
MCQhard

What is the output of the following code? try: raise ValueError('a') except ValueError as e: print(e.args[0]) finally: print('b')

A.a b
B.b a
C.a\nb
D.b
AnswerC

"a\nb" is the exact output. The raise ValueError in the try block transfers control to the except ValueError handler, whose print('a') writes 'a' plus a newline. After that handler finishes, the finally block unconditionally runs and print('b') writes 'b' plus a newline, yielding two lines: first 'a', second 'b'.

Why this answer

The `finally` block always executes after the `try` block, even when an exception is raised. The `except` block catches the `ValueError` and prints the first argument of the exception (`'a'`), then the `finally` block prints `'b'`. The output is `a` on one line and `b` on the next, matching `a\nb`.

Exam trap

Python Institute often tests the misconception that `finally` runs before `except` or that `print()` outputs on the same line, leading candidates to choose options with incorrect order or missing newlines.

How to eliminate wrong answers

Option A is wrong because it suggests both outputs appear on the same line (`a b`), but `print()` adds a newline by default, so they appear on separate lines. Option B is wrong because it reverses the order to `b a`, but the `finally` block executes after the `except` block, not before. Option D is wrong because it omits the `'a'` output entirely, but the `except` block does execute and prints the exception argument before the `finally` block runs.

370
MCQhard

A package 'mypkg' has the following structure: mypkg/ __init__.py submod1.py submod2.py The __init__.py file contains: from . import submod1, submod2. A user runs 'import mypkg' and then 'mypkg.submod1.func()'. However, the user got an AttributeError. What is the most likely cause?

A.submod1 is actually a package, not a module, so it cannot be called with 'func()'.
B.The __init__.py should use absolute imports like 'import mypkg.submod1' to make submod1 accessible.
C.The submod1 module does not define a function named 'func'.
D.The user must also run 'from mypkg import submod1' before accessing submod1.
AnswerC

This is the correct diagnosis because the Python error 'AttributeError: module 'mypkg.submod1' has no attribute 'func'' means the module was successfully loaded, but the requested attribute 'func' is simply not present at the module's top level. This can happen if the function was never defined, is misspelled, or was removed. Attribute lookup on a module object checks its namespace, and a missing key raises AttributeError — not ImportError. The fix is to define func in submod1 (or import it there) before calling it.

Why this answer

The AttributeError indicates that the attribute 'func' was not found on the module object 'submod1'. Since the import statement in __init__.py correctly makes submod1 accessible as mypkg.submod1, the only remaining reason for the error is that submod1.py does not define a function named 'func'. The import mechanism itself is working as intended.

Exam trap

Python Institute often tests whether candidates understand that an AttributeError on a module attribute (like a function) is distinct from an ImportError or ModuleNotFoundError, leading them to incorrectly suspect the import mechanism rather than the missing definition in the module.

How to eliminate wrong answers

Option A is wrong because submod1 is a file (submod1.py) in the package directory, not a subpackage; a package would require a subdirectory with its own __init__.py. Option B is wrong because relative imports (from . import submod1) are perfectly valid and equivalent to absolute imports in this context; both make submod1 accessible as mypkg.submod1. Option D is wrong because after 'import mypkg', the __init__.py already imports submod1 into the mypkg namespace, so 'mypkg.submod1' is directly accessible without an additional import statement.

371
MCQhard

A developer wants to ensure that the 'radius' attribute of a Circle class is always non-negative. Which implementation using @property is correct?

A.class Circle:\n def __init__(self, radius):\n self._radius = radius\n def radius(self):\n return self._radius
B.class Circle:\n def __init__(self, radius):\n self._radius = radius\n @property\n def radius(self):\n return self._radius\n @radius.setter\n def radius(self, value):\n if value < 0:\n raise ValueError\n self._radius = value
C.class Circle:\n def __init__(self, radius):\n self.radius = radius\n @property\n def radius(self):\n return self._radius\n @radius.setter\n def radius(self, value):\n if value < 0:\n raise ValueError\n self._radius = value
D.class Circle:\n def __init__(self, radius):\n self.radius = radius\n @property\n def radius(self):\n return self._radius\n def set_radius(self, value):\n self._radius = value
AnswerC

The correct pattern routes initial assignment through the property setter because __init__ says self.radius = radius, not self._radius = radius. Every time radius is set, regardless of whether it's during construction or later, the setter checks the value and raises ValueError for a negative input. The getter then simply returns the validated _radius, giving a clean, consistent public attribute.

Why this answer

It uses the @property decorator to define a getter and @radius.setter to define a setter that validates the radius value before assignment. The __init__ method correctly assigns to self.radius, which triggers the setter, ensuring the initial value is also validated. This pattern enforces the invariant that radius is always non-negative.

Exam trap

Python Institute often tests the subtlety that __init__ must use the property setter (self.radius = radius) rather than directly assigning to the backing attribute (self._radius = radius) to ensure validation applies to the initial value as well.

How to eliminate wrong answers

Option A is wrong because it lacks the @property decorator, so radius is a plain method, not a property; accessing circle.radius would return a bound method, not the stored value. Option B is wrong because __init__ assigns to self._radius directly, bypassing the setter validation, so an initial negative radius would be accepted. Option D is wrong because it defines a set_radius method instead of using @radius.setter, so the property is read-only and assignment to circle.radius would raise an AttributeError.

372
MCQhard

A Python developer is implementing a class that should behave like a sequence and support indexing. Which pair of special methods must be defined to achieve this?

A.__getitem__ and __contains__
B.__setitem__ and __delitem__
C.__iter__ and __next__
D.__getitem__ and __len__
AnswerD

According to the Python data model, a sequence is defined primarily by having a `__len__` method and a `__getitem__` method that accepts integer indices (and optionally slices). Together they give the object a finite length, support `obj[i]` indexing, and implicitly enable iteration via the old-style `__getitem__` fallback. On top of these two, the `collections.abc.Sequence` ABC automatically mixes in `__contains__`, `__iter__`, `__reversed__`, `index`, and `count`, showing how much behavior is derived from just these two methods.

Why this answer

To make a class behave like a sequence and support indexing (e.g., obj[0]), Python requires the __getitem__ method to retrieve items by key. Additionally, the __len__ method is needed to define the length of the sequence, which is used by built-in functions like len() and is part of the sequence protocol. Together, these two methods satisfy the minimal requirements for a sequence-like object that supports indexing.

Exam trap

Python Institute often tests the distinction between the sequence protocol (__getitem__ + __len__) and the iterator protocol (__iter__ + __next__), trapping candidates who think iteration alone enables indexing.

How to eliminate wrong answers

Option A is wrong because __contains__ is used for the 'in' operator (membership testing), not for indexing or sequence behavior. Option B is wrong because __setitem__ and __delitem__ are for mutable sequences that support item assignment and deletion, but indexing (read access) only requires __getitem__; __len__ is still needed for sequence protocol. Option C is wrong because __iter__ and __next__ implement the iterator protocol, which allows iteration but does not provide indexing (e.g., obj[0] would fail without __getitem__).

373
MCQmedium

A class named Counter has a class variable count and an instance method increment. The method is defined as def increment(self): Counter.count += 1. What will be the output after executing the following code? c1 = Counter(); c2 = Counter(); c1.increment(); c2.increment(); print(Counter.count, c1.count, c2.count)

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

The output is 2 2 2 because `count` is a class variable defined on the `Counter` class. Each call to `increment()` modifies the same class-level attribute, not a per-instance copy, so after two increments the shared value becomes 2. Both `c1.count` and `c2.count` resolve to that same class attribute via Python's attribute lookup chain, and `Counter.count` directly reads it, so all three expressions print the identical value 2.

Why this answer

The class variable `count` is shared across all instances of the `Counter` class. The `increment` method modifies `Counter.count` directly, so after two calls, `Counter.count` becomes 2. Since `c1.count` and `c2.count` refer to the same class variable (they do not have instance attributes shadowing it), both instances reflect the same value of 2.

Exam trap

Python Institute often tests the distinction between class variables and instance variables, trapping candidates who mistakenly think each instance gets its own copy of the class variable or that `self.count` would create an instance attribute instead of modifying the class variable.

How to eliminate wrong answers

Option B is wrong because it assumes each instance has its own `count` attribute that increments independently, but the code modifies the class variable, not instance attributes. Option C is wrong because it suggests only one increment occurred, but two calls to `increment()` were made. Option D is wrong because it implies no increment happened at all, ignoring the two calls to `increment()`.

374
Multi-Selecteasy

Which TWO of the following are built-in Python exceptions?

Select 2 answers
A.CustomException
B.InputError
C.ValueError
D.FileNotFoundError
E.FileReadError
AnswersC, D

ValueError is a built-in exception in Python, defined in the `builtins` module and raised when a function receives an argument of the correct type but an invalid value—for example, `int('abc')` or `math.sqrt(-1)`. It is deliberately distinct from `TypeError`, which covers type mismatches, allowing programmers to catch value-specific errors cleanly. As a built-in, it is always available without any import and is part of the core exception hierarchy.

Why this answer

ValueError (C) is a built-in Python exception that is raised when a built-in operation or function receives an argument with the correct type but an inappropriate value, such as int('abc'). FileNotFoundError (D) is a built-in exception in Python 3, raised when a file or directory is requested but does not exist, commonly encountered during file I/O operations like open().

Exam trap

Python Institute often tests the distinction between built-in exceptions and user-defined or non-existent exceptions, and the trap here is that candidates may confuse InputError or FileReadError with real built-in exceptions like EOFError or OSError, or assume that any error related to input or files must be a built-in exception.

375
Multi-Selectmedium

Which TWO statements about the __init__.py file in a Python package are true?

Select 2 answers
A.It must contain at least one import statement to be valid.
B.It is mandatory for all packages, including namespace packages.
C.It prevents submodules from being imported directly.
D.It can define the __all__ list to control what is exported with 'from package import *'.
E.It is executed when the package is first imported.
AnswersD, E

Defining `__all__` in __init__.py is the canonical way to specify which names are exported when `from package import *` is used, effectively controlling the package's public API. Only the names listed in `__all__` (and not explicitly excluded) are bound in the importing namespace, allowing explicit control over what users can access via star imports.

Why this answer

The `__all__` list in `__init__.py` explicitly defines the public API of a package, controlling which names are exported when a client uses `from package import *`. This is a standard Python mechanism to prevent unintended internal modules from being exposed.

Exam trap

Python Institute often tests the misconception that `__init__.py` is mandatory for all packages, including namespace packages, and that it must contain code to be valid, when in fact it can be empty and is optional for namespace packages.

Page 4

Page 5 of 6

Page 6

All pages