Courseiva

Certified Associate Python Programmer PCAP (PCAP) — Questions 226–300

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

Page 3

Page 4 of 6

Page 5
226
MCQmedium

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

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

Class attributes are shared across all instances, so mutating the cached dictionary propagates everywhere. Defining it inside __init__ binds a fresh dictionary to each instance's namespace, satisfying the requirement that every instance holds its own independent configuration copy.

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

227
MCQeasy

A developer wants to ensure that a class attribute is shared among all instances but cannot be modified from outside the class. Which approach is most appropriate?

A.Use a property decorator on a class method
B.Define a public class attribute and document it as read-only
C.Define an instance attribute inside __init__
D.Define a private class attribute (e.g., __shared) and provide a class method to access it
AnswerD

Defining `__shared` inside the class body but outside `__init__` puts it in the class namespace, and Python's name mangling rewrites it to `_ClassName__shared`, which discourages accidental external access. A `@classmethod` getter (for example `cls.__shared`) can return the value to all callers without exposing a writable descriptor; while a determined caller could still use the mangled name, the mangling plus getter signals that the attribute is private and read-only. This achieves shared state across every instance and gives a single controlled access point.

Why this answer

Defining a private class attribute with name mangling (e.g., `__shared`) prevents direct external modification, and providing a class method (using `@classmethod`) allows read-only access to the attribute. This ensures the attribute is shared among all instances (since it belongs to the class, not instances) while enforcing encapsulation.

Exam trap

Python Institute often tests the distinction between class-level and instance-level attributes, and the trap here is that candidates confuse the `@property` decorator (which works on instance methods) with class-level read-only access, or assume documentation alone provides protection.

How to eliminate wrong answers

Option A is wrong because a property decorator is designed for instance attributes, not class attributes; applying it to a class method would not create a shared, read-only class-level attribute. Option B is wrong because documenting a public class attribute as read-only does not enforce immutability — external code can still modify it directly, violating the requirement. Option C is wrong because an instance attribute defined inside `__init__` is unique to each instance, not shared among all instances.

228
MCQeasy

A user runs script.py and gets the above error: ModuleNotFoundError: No module named 'mypackage'. Which of the following is the most likely cause?

A.The function myfunction does not exist in mypackage.
B.The script.py is inside the mypackage directory, causing a conflict.
C.The package mypackage is not installed or not in the Python path.
D.There is a syntax error in script.py.
AnswerC

ModuleNotFoundError: No module named 'mypackage' means the import system searched all entries in sys.path and found no module or package named 'mypackage'. This happens when the package is not installed (e.g., not in site-packages), the current working directory is not on sys.path, or the package's parent directory is not listed in the Python path. The fix is to install the package or adjust PYTHONPATH/sys.path so that the import machinery can locate it.

Why this answer

The error message 'ModuleNotFoundError: No module named 'mypackage'' indicates that Python cannot find the module 'mypackage'. This typically occurs when the package is not installed or not present in sys.path. Option C directly addresses this cause.

The other options are less plausible: Option A would raise an AttributeError, not a ModuleNotFoundError; Option B might cause import issues but would likely result in a circular import error or import error due to naming conflicts; Option D's syntax error would prevent the script from running at all. Therefore, Option C is the most probable cause.

Exam trap

Python Institute often tests the distinction between `ImportError` (module not found) and `AttributeError` (module found but attribute missing), so candidates mistakenly choose Option A when they see an import-related error, confusing a missing module with a missing function within an existing module.

How to eliminate wrong answers

Option A is wrong because if `myfunction` did not exist in `mypackage`, the error would be an `AttributeError` (e.g., 'module 'mypackage' has no attribute 'myfunction''), not an `ImportError` about the package itself. Option B is wrong because placing `script.py` inside the `mypackage` directory would not cause an `ImportError`; it would actually make the import succeed (assuming `__init__.py` exists), though it could lead to circular imports or naming conflicts, but not the error shown. Option D is wrong because a syntax error in `script.py` would produce a `SyntaxError` at compile time, not an `ImportError` at runtime; the error message explicitly mentions 'ImportError', which is unrelated to syntax issues.

229
Multi-Selecthard

Which THREE of the following are true about the `with` statement for file handling?

Select 3 answers
A.It can only be used with files.
B.It can only handle one file at a time.
C.It uses the __enter__ and __exit__ methods of the file object.
D.It ensures the file is closed even if an exception occurs inside the block.
E.It automatically closes the file when the block exits.
AnswersC, D, E

When entering a `with` block, Python calls the `__enter__` method on the context manager and assigns its return value to the `as` variable. Upon block exit, it always calls the `__exit__` method, which for a file object performs the actual closing operation. This pair of methods forms the core of the context manager protocol, and the `with` statement is simply a wrapper that guarantees both calls.

Why this answer

The `with` statement relies on the context management protocol, which requires the object to implement the `__enter__` and `__exit__` methods. When a file object is used with `with`, its `__enter__` method returns the file object itself, and its `__exit__` method is called upon block exit to handle cleanup, such as closing the file.

Exam trap

Python Institute often tests the misconception that `with` is only for files, but the trap here is that candidates may also incorrectly think it can only handle one file at a time, while Python actually supports multiple context managers in a single `with` statement.

230
MCQmedium

A file is opened with open('test.txt', 'r'). The file object's tell() method returns 0. After reading 10 characters, what does tell() return?

A.File size
B.0
C.-1
D.10
AnswerD

After reading 10 bytes (or characters, in text mode on most platforms) from the beginning of the file, the file pointer has advanced from offset 0 to offset 10. Calling tell() immediately after the read returns 10, which correctly reflects that new position in the stream. This is why 10 is the accurate answer: tell() always mirrors the exact number of bytes the read operation has consumed from the start.

Why this answer

The `tell()` method returns the current position of the file pointer in bytes from the beginning of the file. After reading 10 characters (each being 1 byte in a typical text file), the pointer advances by 10 bytes, so `tell()` returns 10.

Exam trap

Python Institute often tests the misconception that `tell()` returns the number of characters read or the file size, when in fact it returns the byte offset from the start of the file.

How to eliminate wrong answers

Option A is wrong because `tell()` does not return the file size; it returns the current offset, not the total length. Option B is wrong because the file pointer moves after reading, so it cannot remain at 0. Option C is wrong because `tell()` never returns -1; it always returns a non-negative integer representing the byte offset.

231
Multi-Selectmedium

A backup utility writes a manifest with `with open('manifest.txt', 'w') as out:`. The developer needs to ensure that partial writes are not silently left in the file when an exception occurs mid-loop. Which two statements about using a try/except/else/finally structure around this write loop are correct? (Choose two.)

Select 2 answers
A.The finally block executes even if an except clause handles the exception and the handler itself raises a new exception.
B.Code in the else block runs before the except clauses are evaluated, so it can change which handler is selected.
C.A return statement inside the try block prevents the finally block from executing.
D.The else block runs only when the try block completes without raising an exception.
E.If an except clause handles the exception, the finally block is skipped because the error was already resolved.
AnswersA, D

finally is guaranteed to run during the unwinding of the try statement regardless of whether an exception occurred, was handled, or was replaced by a new exception inside a handler. This guarantee is what makes finally suitable for cleanup such as removing a temporary manifest file or releasing a lock.

Why this answer

In a try/except/else/finally statement, else runs only when the try suite finishes without an exception, and finally runs unconditionally during unwinding, including when a handler raises or when try exits via return. Those two guarantees let the developer mark success in else and perform unconditional cleanup in finally, protecting against partially written manifests.

Exam trap

The trap here is assuming that a handled exception or an early return cancels the finally suite, when finally is designed to run during every form of exit from the statement.

232
Multi-Selectmedium

Which TWO statements about namespace packages are true?

Select 2 answers
A.They are automatically created when a directory containing .py files is added to sys.path.
B.They are supported in Python 3.3 and later.
C.They allow a single package to be distributed across multiple directories.
D.They can only contain __init__.py files.
E.They require an __init__.py file.
AnswersB, C

Namespace packages were introduced in Python 3.3 via PEP 420, which rewrote the import machinery to allow packages to exist without an __init__.py file. Before that release, every package had to contain __init__.py, and a directory without it was not importable as a package. Therefore, the namespace package concept is supported only in Python 3.3 and later.

Why this answer

Namespace packages were introduced in Python 3.3 via PEP 420. They allow a package to be split across multiple directories on sys.path without requiring an __init__.py file, enabling logical grouping of subpackages from different locations.

Exam trap

Python Institute often tests the misconception that all packages require an __init__.py file, but namespace packages are a deliberate exception introduced in Python 3.3, and candidates may incorrectly assume that any directory with .py files automatically becomes a namespace package.

233
MCQmedium

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

234
MCQmedium

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

235
MCQmedium

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

236
MCQmedium

A programmer writes a class with a static method using @staticmethod. What is the primary purpose of using a static method instead of a class method or instance method?

A.To access class variables without creating an instance
B.To define a method that does not depend on class or instance state and behaves like a regular function but is namespaced inside the class
C.To allow the method to be overridden in subclasses
D.To enforce that the method cannot be called from an instance
AnswerB

A staticmethod is a method that has no dependency on either the class or an instance: Python does not pass an implicit first argument, so the function signature stays exactly as written. It behaves like a plain module-level function but is namespaced inside the class to keep related utilities organized. This makes it ideal for helper logic that doesn't need or receive class/instance context, such as input validation or format conversion, while still being callable from both the class and instances.

Why this answer

A static method in Python, decorated with @staticmethod, does not receive an implicit first argument (neither self nor cls). This means it cannot access or modify class or instance state; it behaves exactly like a regular function but is organized within the class's namespace for logical grouping. The primary purpose is to encapsulate utility functions that are related to the class but do not depend on its data.

Exam trap

Python Institute often tests the distinction between static and class methods by making candidates think that @staticmethod is used to access class variables, when in fact that is the role of @classmethod, and the trap is that both decorators avoid the need for an instance, but only @classmethod receives the class reference.

How to eliminate wrong answers

Option A is wrong because accessing class variables without an instance is the purpose of a class method (decorated with @classmethod), which receives the class as the first argument (cls) and can read or write class-level attributes; a static method has no access to cls and cannot directly access class variables unless they are passed explicitly. Option C is wrong because static methods are not overridden in subclasses in the same way as instance or class methods; they are resolved at compile time (early binding) and do not participate in the normal method resolution order (MRO) for inheritance, so overriding them has no effect when called on the subclass. Option D is wrong because static methods can be called from an instance just fine; Python allows calling any method from an instance, and @staticmethod does not restrict this — the decorator only removes the implicit self parameter, not the ability to invoke it on an object.

237
MCQhard

A programmer writes a context manager to manage a temporary file. The class implements __enter__ to open the file and return the handle, and __exit__ to close it. During the with body, an exception is raised. The programmer wants the exception to propagate after cleanup. What should __exit__ return in this case?

A.True
B.The file handle returned by open()
C.None, only after re-raising the exception with raise
D.False
AnswerD

The __exit__ method receives the exception type, value, and traceback, and its return value controls suppression. Returning False (or a falsy value such as None) means the exception is not suppressed and will propagate after __exit__ finishes. In this scenario the programmer wants the exception to propagate, so returning False after closing the file satisfies the requirement while still performing cleanup.

Why this answer

The __exit__ return value is a suppression flag: a falsy result lets the exception propagate, while a truthy result suppresses it. Since the goal is to clean up the temporary file and still surface the error, returning False is correct. Returning a handle or re-raising inside __exit__ would either hide the exception or replace it with a different one.

Exam trap

The trap here is assuming that __exit__ returning the file handle is a valid cleanup pattern, when any truthy return value suppresses the exception.

238
MCQhard

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

239
MCQeasy

A programmer has a string 'apple,banana,orange' and wants to get a list ['apple', 'banana', 'orange']. Which method should be used?

A.s.splitlines()
B.s.partition(',')
C.s.join(',')
D.s.split(',')
AnswerD

s.split(',') is correct because str.split() with a specified separator splits the string at every occurrence of that separator and returns a list of the substrings in between, with the separator removed. For the string 'apple,banana,orange', this yields ['apple', 'banana', 'orange'], exactly the three separate fruits the programmer wants. This is the standard built-in method for turning a delimited string into a list of parts.

Why this answer

`s.split(',')` splits the string `'apple,banana,orange'` at each comma delimiter, returning a list of substrings: `['apple', 'banana', 'orange']`. This method is designed to break a string into a list based on a specified separator, making it the exact tool for this task.

Exam trap

The PCAP exam often tests the confusion between `split()` and `partition()` — candidates mistakenly think `partition()` returns a list of all parts, but it only splits at the first occurrence and returns a tuple, not a list of all comma-separated items.

How to eliminate wrong answers

Option A is wrong because `s.splitlines()` splits a string at line boundaries (e.g., newline characters), not at commas, so it would return a single-element list `['apple,banana,orange']` if no newlines are present. Option B is wrong because `s.partition(',')` returns a tuple of three elements: the part before the first comma, the comma itself, and the rest after it (e.g., `('apple', ',', 'banana,orange')`), not a list of all comma-separated items. Option C is wrong because `s.join(',')` is a string method that concatenates an iterable of strings with the separator, but calling it on a string like `s` (which is not an iterable of strings) raises a `TypeError`; it is the inverse of `split()` and cannot produce a list from a single string.

240
MCQeasy

A developer needs to add a custom directory '/home/user/mylibs' to Python's module search path so that modules in that directory can be imported. Which code snippet accomplishes this correctly?

A.import sys; sys.path.append('/home/user/mylibs')
B.import sys; sys.path.push('/home/user/mylibs')
C.import sys; sys.path.add('/home/user/mylibs')
D.import path; path.add('/home/user/mylibs')
AnswerA

This is the correct approach. The sys.path attribute is a list of directory strings that Python searches in order when resolving imports. list.append() is the standard method for adding a single element to the end of the list, so /home/user/mylibs becomes available for subsequent import statements, though only for the current process.

Why this answer

Python's module search path is stored in the list `sys.path`, and the standard way to add a custom directory at runtime is to use the `list.append()` method. This inserts the directory at the end of the search path, allowing modules in that directory to be imported after the standard library and site-packages directories.

Exam trap

The trap here is that candidates may confuse `sys.path` with a stack or set and choose a method like `push()` or `add()` that does not exist for Python lists, or they may incorrectly import a non-existent `path` module instead of `sys`.

How to eliminate wrong answers

Option B is wrong because `sys.path` is a list, and Python lists do not have a `push()` method (that is a method of stacks in other languages, not Python). Option C is wrong because `sys.path` is a list, and lists do not have an `add()` method (that method belongs to sets, not lists). Option D is wrong because there is no standard `path` module in Python that provides an `add()` function for modifying the module search path; the correct module is `sys` and the attribute is `sys.path`.

241
MCQmedium

A developer runs pip install package==1.0 and gets the above error. What is the most likely solution?

A.Run pip update to upgrade pip.
B.Install from a different repository.
C.Use pip install package==2.0 instead.
D.Check if the package name is correct.
AnswerC

Use pip install package==2.0 because the error message explicitly lists 2.0 as the only available version; requesting that exact version aligns the requirement with what the index can supply. '==' is an exact version pin, so pip will select that version without ambiguity. This resolves the immediate failure, and if an older pin is needed, the dependency requirement must be updated rather than the environment.

Why this answer

The error indicates that version 1.0 of the package does not exist in the repository. By specifying a higher version like 2.0 that does exist, pip can successfully download and install the package. This is a common scenario when a package has never released version 1.0 or has skipped it.

Exam trap

Python Institute often tests the distinction between a missing package name and a missing version number, tricking candidates into checking the name or repository when the error specifically says the version is unavailable.

How to eliminate wrong answers

Option A is wrong because 'pip update' is not a valid pip command; the correct command is 'pip install --upgrade pip', and upgrading pip would not resolve a missing version error. Option B is wrong because the error is about a specific version not being found, not about repository accessibility or authentication; changing the repository would not help if the package itself does not have that version. Option D is wrong because the error message explicitly states the package name was found but version 1.0 is not available, so the name is correct.

242
MCQmedium

A programmer has a string s = 'Python programming is fun'. They want to extract the word 'programming'. Which slicing expression achieves this?

A.s[6:18]
B.s[7:18]
C.s[7:19]
D.s[6:19]
AnswerB

This is the correct slice. Python's slice s[start:stop] includes characters from start up to, but not including, stop; therefore s[7:18] returns the characters at indices 7 through 17, which spell exactly 'programming'. The start index 7 points to the first letter 'p', and the exclusive stop index 18 excludes the space that immediately follows the word, ensuring a precise extraction.

Why this answer

Python uses zero-based indexing. The word 'programming' starts at index 7 (the character 'p' in 'programming') and ends at index 17 (the character 'g'), but slicing is exclusive of the end index, so s[7:18] extracts characters from index 7 up to but not including index 18, which gives 'programming'.

Exam trap

The PCAP exam often tests the off-by-one error in slicing, where candidates forget that the stop index is exclusive, leading them to choose options that include an extra character or miss the correct substring.

How to eliminate wrong answers

Option A is wrong because s[6:18] starts at index 6, which is the space before 'programming', resulting in ' programming' (with a leading space). Option C is wrong because s[7:19] ends at index 19, which is the space after 'programming', resulting in 'programming ' (with a trailing space). Option D is wrong because s[6:19] starts at index 6 (space) and ends at index 19 (space after 'programming'), producing ' programming ' (with leading and trailing spaces).

243
MCQhard

A developer writes a class `Vector` and wants `v1 + v2` to return a brand-new `Vector`, while `v1 += v2` should mutate `v1` in place and return it. Which pair of special methods achieves this behaviour?

A.`__add__` returning a new `Vector`, and `__radd__` mutating `self` and returning `self`.
B.`__add__` mutating `self` and returning `self`, and `__radd__` returning a new `Vector`.
C.`__add__` returning a new `Vector`, and `__iadd__` mutating `self` and returning `self`.
D.`__iadd__` returning a new `Vector`, and `__add__` mutating `self` and returning `None`.
AnswerC

`__add__` is invoked for the binary `+` operator and conventionally returns a new object, which satisfies the first requirement. `__iadd__`, when defined, is called by the augmented assignment `+=`; mutating the instance and returning it makes `v1 += v2` update the existing object rather than rebinding the name to a new one. Together they produce exactly the two distinct behaviours requested.

Why this answer

Defining `__add__` for the binary plus operator and `__iadd__` for augmented assignment is the idiomatic way to separate non-mutating and in-place semantics. The binary method returns a fresh instance so operands are left untouched, while the in-place method mutates the receiver and returns it so the same object identity is preserved after `+=`. Reflected methods such as `__radd__` serve a different purpose and cannot substitute for either.

Exam trap

The trap here is believing `__radd__` participates in `v1 += v2`, when it only handles reflected operations where the left operand cannot perform the addition.

244
MCQmedium

A Python package 'analytics' contains a subpackage 'models' with module 'regression.py'. Inside 'regression.py', there is a function 'linear_fit' that depends on 'numpy'. The developer wants to ensure that 'numpy' is imported only once and available throughout the package. Where should the import 'import numpy as np' be placed?

A.In the '__init__.py' of the 'models' subpackage.
B.In each module that uses numpy, add 'import numpy as np'.
C.In the '__init__.py' of the 'analytics' top-level package.
D.In a separate file 'common_imports.py' and import that file everywhere.
AnswerB

Adding 'import numpy as np' in every module that uses numpy is the standard explicit approach, but it only populates that module's local namespace with np. It does not define numpy as a package attribute such as analytics.np, and it does not establish a single import point that all package code can rely on. If the version or alias ever changes, every module must be edited individually, which defeats the goal of a shared common import.

Why this answer

To use numpy in regression.py, that module must have its own import statement, e.g., 'import numpy as np'. Python caches modules in sys.modules, so loading happens only once regardless of where the import statement appears. Thus, repeating 'import numpy as np' in each module that needs it is both correct and efficient, and it respects namespace isolation.

Exam trap

The trap is the misconception that package-level __init__.py imports are necessary to avoid multiple imports or to share names across modules. In reality, Python's caching prevents redundant execution, and name visibility is not automatic.

How to eliminate wrong answers

Option A is wrong because placing the import in the '__init__.py' of the 'models' subpackage would only make numpy available within that subpackage, not throughout the entire 'analytics' package, and it would be imported each time the subpackage is loaded. Option B is wrong because importing numpy in each module that uses it would cause multiple imports, which, while technically allowed due to caching, violates the requirement to import it only once and does not ensure availability throughout the package without explicit imports. Option D is wrong because using a separate 'common_imports.py' file and importing it everywhere still requires explicit imports in each module, and it does not guarantee that numpy is imported only once at the package level; it also adds unnecessary indirection without leveraging Python's package initialization mechanism.

245
Drag & Dropmedium

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

Drag or tap steps into the slots.

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

Why this order

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

246
MCQmedium

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

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

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

Why this answer

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

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

Exam trap

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

How to eliminate wrong answers

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

247
Multi-Selecthard

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

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

The 'with' statement works with any object implementing the context manager protocol, namely __enter__ and __exit__. This duck-typing behaviour means files, locks, sockets and custom classes all qualify, without requiring inheritance from a specific base class.

Why this answer

Option A is correct because the context manager protocol is defined precisely by the presence of __enter__ and __exit__ methods, so any object implementing both can be used with 'with'. Option B is correct because the 'with' statement's semantics ensure __exit__ is invoked when the block exits, whether normally or via an exception, which is the core guarantee of the protocol. Option C is correct because Python supports 'with A() as a, B() as b:' syntax, allowing multiple context managers separated by commas (equivalent to nested with statements).

Option D is not marked correct because while 'with' often replaces try/finally for resource cleanup, it does not eliminate the need for try/finally in all cases, such as when no context manager exists or when cleanup logic must run without one. Option E is not marked correct because 'with' works with any context manager, not only file objects; files are just a common example.

Exam trap

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

248
Drag & Dropmedium

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

Drag or tap steps into the slots.

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

Why this order

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

249
MCQeasy

What is the result of the expression 'aBc'.lower()?

A.'abc'
B.'Abc'
C.'aBc'
D.'ABC'
AnswerA

Calling lower() on the string 'aBc' returns a new string where every cased character has been converted to its lowercase form: the leading 'a' is already lowercase and stays 'a', while the uppercase 'B' becomes 'b'. The result is therefore exactly 'abc' — a three-character string with no uppercase letters remaining. This is the documented behavior of str.lower() in Python.

Why this answer

The `lower()` method returns a new string with all cased characters converted to lowercase. Since the original string 'aBc' contains an uppercase 'B', calling `.lower()` converts it to 'b', resulting in 'abc'. The method does not modify the original string but returns a new one.

Exam trap

Python Institute often tests whether candidates understand that `.lower()` does not modify the original string but returns a new one, and that it only affects uppercase letters, not other characters like digits or symbols.

How to eliminate wrong answers

Option B is wrong because 'Abc' would result from calling `.capitalize()` or `.title()`, not `.lower()`. Option C is wrong because it is the original string unchanged, but `.lower()` always returns a new string with all characters lowercased. Option D is wrong because 'ABC' would result from calling `.upper()`, not `.lower()`.

250
MCQmedium

A script uses `with open('data.bin', 'rb') as f:` to read binary data. Within the block, which method should be used to read exactly 4 bytes?

A.f.read(4)
B.f.seek(4)
C.f.readline()
D.f.read()
AnswerA

Calling f.read(4) on a binary file opened with mode 'rb' reads at most 4 bytes from the current file position, returning them as a bytes object. This is precisely the intended operation for reading a fixed-size chunk, which is essential when parsing binary formats that store data in fixed-width fields, such as integers or headers. The size argument caps the read length, so the file pointer advances by exactly the number of bytes actually read, and it handles end-of-file gracefully by returning fewer than 4 bytes.

Why this answer

The `read(n)` method reads exactly `n` bytes from the file object when the file is opened in binary mode (`'rb'`). Since the question specifies reading exactly 4 bytes, `f.read(4)` is the correct and direct approach. This method returns a bytes object of up to `n` bytes, but if the file has at least 4 bytes remaining, it will return exactly 4.

Exam trap

Python Institute often tests the distinction between `read()` (reads entire file), `read(n)` (reads exactly n bytes), and `seek()` (moves pointer without reading), and the trap here is that candidates may confuse `seek(4)` with reading 4 bytes, or assume `read()` without arguments reads a fixed number of bytes.

How to eliminate wrong answers

Option B is wrong because `f.seek(4)` moves the file pointer to byte offset 4 from the beginning, but does not read any data. Option C is wrong because `f.readline()` reads until a newline byte (`\n`) or EOF, which is not guaranteed to return exactly 4 bytes and is intended for text-based line reading, not fixed-size binary reads. Option D is wrong because `f.read()` with no argument reads the entire remaining contents of the file into memory, which will almost certainly not be exactly 4 bytes unless the file itself is exactly 4 bytes long.

251
MCQhard

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

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

Implementing area() in Rectangle satisfies the abstract-method contract inherited from Shape, so instantiation no longer raises TypeError. Python's ABCMeta blocks instantiation while any abstract method remains unimplemented; providing a concrete override in the subclass clears that check. Multiple inheritance from Drawable is unaffected, since mixins impose no abstract requirements here.

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

252
Multi-Selectmedium

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

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

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

Why this answer

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

Exam trap

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

253
MCQmedium

A programmer needs to replace every occurrence of 'cat' with 'dog' in a string s, but only if 'cat' is not preceded by 'big'. Which regex substitution would achieve this?

A.re.sub(r'bigcat', 'dog', s)
B.re.sub(r'cat', 'dog', s)
C.re.sub(r'(?<=big)cat', 'dog', s)
D.re.sub(r'(?<!big)cat', 'dog', s)
AnswerD

The negative lookbehind (?<!big) is a zero-width assertion that succeeds only when the characters immediately before the current position are not 'big'; if they are, the match attempt at that location fails. As a result, every 'cat' that is not part of 'bigcat' is replaced with 'dog', while 'bigcat' stays exactly as is. This correctly replaces all occurrences of 'cat' except those preceded by 'big'.

Why this answer

Uses a negative lookbehind assertion `(?<!big)` to match 'cat' only when it is NOT preceded by 'big'. This ensures that 'bigcat' remains unchanged while standalone 'cat' is replaced with 'dog'. The `re.sub` function then substitutes all such matches in the string.

Exam trap

The PCAP exam often tests the distinction between positive and negative lookbehinds, and the trap here is that candidates confuse `(?<=...)` (match if preceded by) with `(?<!...)` (match if NOT preceded by), leading them to choose Option C instead of D.

How to eliminate wrong answers

Option A is wrong because it matches the literal string 'bigcat' and replaces the entire sequence with 'dog', which would turn 'bigcat' into 'dog' instead of leaving it unchanged. Option B is wrong because it replaces every occurrence of 'cat' regardless of context, including those preceded by 'big'. Option C is wrong because it uses a positive lookbehind `(?<=big)` which matches 'cat' only when it IS preceded by 'big', the exact opposite of the requirement.

254
MCQmedium

What is the output of the following code? try: print(1/0) except: print('err') finally: print('fin')

A.fin err
B.fin
C.err fin
D.err
AnswerC

After an exception is raised in the try block, Python finds the matching except clause and executes its body, printing "err". The finally clause then executes unconditionally as part of exception handling, printing "fin" after the except handler completes. Thus the full and correct output is "err fin".

Why this answer

When a division by zero occurs, Python raises a ZeroDivisionError, which is caught by the bare except clause, printing 'err'. The finally clause always executes after the except block, printing 'fin'. Thus the output is 'err' followed by 'fin'.

Exam trap

Python Institute often tests the order of execution in try/except/finally blocks, specifically that the except block runs before the finally block when an exception is caught, and that the finally block always executes even if no exception occurs.

How to eliminate wrong answers

Option A is wrong because it shows 'fin err', implying the finally block runs before the except block, but in Python the except block runs first when an exception is caught. Option B is wrong because it shows only 'fin', ignoring that the except block prints 'err' when the exception is caught. Option D is wrong because it shows only 'err', omitting the finally block which always executes regardless of whether an exception occurs or is caught.

255
MCQeasy

What is the output of 'hello'.count('l')?

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

The expression 'hello'.count('l') correctly returns 2, the total number of non-overlapping occurrences of the character 'l' in the string. Python's str.count() method counts each match from left to right, and since 'hello' consists of 'h', 'e', 'l', 'l', 'o', it finds an 'l' at position 2 and another at position 3 (0-based). Therefore, the output is exactly 2.

Why this answer

The string method `count('l')` returns the number of non-overlapping occurrences of the substring `'l'` in the string `'hello'`. The string `'hello'` contains the character `'l'` at indices 2 and 3, so the count is 2. Therefore, option D is correct.

Exam trap

Python Institute often tests the `count()` method with a single character substring to see if candidates correctly count occurrences, but the trap here is that some candidates might mistakenly count the total number of characters or misremember the string `'hello'` as having only one `'l'`.

How to eliminate wrong answers

Option A is wrong because it suggests only one `'l'` is present, but `'hello'` has two `'l'` characters. Option B is wrong because it counts three `'l'` characters, which would be true only for a string like `'lll'` or if the candidate mistakenly counts the `'l'` in `'hello'` three times. Option C is wrong because it indicates no `'l'` is found, which is incorrect as `'hello'` clearly contains two `'l'` characters.

256
MCQmedium

Which of the following demonstrates that strings are immutable?

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

257
MCQhard

A developer defines a class 'A' with a method 'm' that uses 'self.a'. Class 'B' inherits from 'A' and defines __init__ that sets 'self.a = 10'. An instance of B is created and method m is called. What is the output?

A.None
B.AttributeError
C.10
D.0
AnswerC

The method m, inherited from A, executes with self bound to a B instance. During instantiation, B.__init__ executes self.a = 10, placing a in the instance's __dict__. Consequently, the expression inside m that uses a evaluates to 10, matching the assigned value exactly.

Why this answer

When an instance of class B is created, its __init__ method sets self.a = 10. When method m (inherited from A) is called on that instance, self refers to the B instance, so self.a resolves to 10. Python's attribute lookup follows the instance's __dict__ first, finding the attribute set by B's __init__.

Exam trap

Python Institute often tests the misconception that inherited methods use the parent class's attribute values rather than the instance's own attributes, leading candidates to incorrectly expect an AttributeError or None.

How to eliminate wrong answers

Option A is wrong because self.a is not None; it is explicitly set to 10 in B.__init__, so the output is not None. Option B is wrong because there is no AttributeError; the attribute a exists on the instance due to B.__init__, so the lookup succeeds. Option D is wrong because self.a is not 0; it is assigned the integer 10, not a default or zero value.

258
MCQmedium

A class `Vector` defines `__add__` to return a new `Vector`. A developer writes `v1 = Vector(1,2); v2 = Vector(3,4); v3 = v1 + v2`. What is the type of `v3`?

A.`None`
B.`Vector`
C.`int`
D.`tuple`
AnswerB

When `v1 + v2` is evaluated, Python calls `v1.__add__(v2)`. If `__add__` is implemented to return a new `Vector` instance, then `v3` will be of type `Vector`. This is the expected behavior for operator overloading in Python, allowing custom objects to support arithmetic operations.

Why this answer

Operator overloading in Python allows classes to define behavior for operators like `+`. The `__add__` method is called on the left operand, and its return value becomes the result of the expression. Since the `Vector` class implements `__add__` to return a new `Vector`, `v3` is a `Vector` instance.

Exam trap

The trap here is assuming that `+` always returns a numeric type, but with operator overloading, it can return any type.

259
MCQhard

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

260
Multi-Selecteasy

Which TWO of the following are valid uses for the '__name__' variable in a Python module?

Select 2 answers
A.To get the file path of the module.
B.To control which names are exported when using 'from module import *'.
C.To determine which module imported it.
D.To check if the module is being run as the main program.
E.To get the fully qualified name of the module (e.g., 'package.module').
AnswersD, E

When a module is executed directly as a script, Python assigns the literal string '__main__' to its __name__ attribute, whereas an imported module receives its normal dotted name. Comparing __name__ to '__main__' thus allows you to detect whether the current file is the entry point of the program. This pattern is the standard way to protect executable code so it runs only when the file is launched directly, not when it is imported by another module.

Why this answer

The '__name__' variable is set to the string '__main__' when the module is executed directly as the main program (e.g., via 'python module.py'). This allows a module to include code that runs only when it is the entry point, not when it is imported by another module. The check is typically done with 'if __name__ == "__main__":'.

Exam trap

The trap here is that candidates often confuse '__name__' with '__file__' (for file paths) or '__all__' (for export control), and may incorrectly think '__name__' can identify the importing module, which Python does not directly support.

261
Multi-Selectmedium

Which TWO statements about the sys module are true?

Select 2 answers
A.sys.path is a tuple of module search paths.
B.sys.modules is a list of all loaded modules.
C.sys.exit() raises SystemExit with a default exit code of 0.
D.The sys module is automatically imported in every Python script.
E.sys.argv[0] is the script name.
AnswersC, E

Calling sys.exit() stops a Python program by raising the SystemExit exception, and when no status argument is supplied the exit code is 0, meaning successful termination. The absence of an argument is equivalent to passing None, which the interpreter treats as 0 for the process exit status. Because SystemExit is an exception, code in finally blocks still runs, and an outer try/except can intercept it, so sys.exit() is not an abrupt low-level kill.

Why this answer

`sys.exit()` raises the `SystemExit` exception, and when called without an argument, the default exit code is 0, indicating successful termination. This behavior is defined in the Python documentation for the `sys` module.

Exam trap

Python Institute often tests the distinction between mutable and immutable types (list vs. tuple) and between data structures (list vs. dict) for `sys.path` and `sys.modules`, as well as the fact that `sys` is not a built-in module that is auto-imported.

262
MCQmedium

What is the result of 'Python'.find('th')?

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

Indexing 'python' from zero gives p=0, y=1, t=2, h=3, o=4, n=5; the two-character substring 'th' begins at offset 2, where 't' resides and is followed immediately by 'h'. Python's str.find returns the lowest zero-based index at which the substring starts, so 'python'.find('th') evaluates to exactly 2. This is the correct result.

Why this answer

The string method `find()` returns the lowest index where the substring is found. In 'Python', the substring 'th' starts at index 2 (P=0, y=1, t=2, h=3, o=4, n=5). Therefore, the result is 2, making option C correct.

Exam trap

Python Institute often tests the zero-based indexing of strings, leading candidates to mistakenly count from 1 instead of 0, or to confuse `find()` with `index()` and expect an exception for missing substrings.

How to eliminate wrong answers

Option A is wrong because 1 would be the index of 'y', not the start of 'th'. Option B is wrong because -1 is returned only when the substring is not found, but 'th' is present in 'Python'. Option D is wrong because 0 would be the index of 'P', not the start of 'th'.

263
MCQeasy

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

264
MCQhard

When a class defines both __getattr__ and __getattribute__, which one is called when accessing an attribute that exists in the instance?

A.__getattr__ always overrides __getattribute__.
B.Both __getattr__ and __getattribute__ are called, in that order.
C.Only __getattr__ is called.
D.__getattribute__ is called, and __getattr__ is not called.
AnswerD

For a normal attribute that exists on the instance or class, __getattribute__ is invoked and successfully returns the value, so Python never proceeds to the __getattr__ fallback. This is the correct behavior when a class defines both hooks: the primary lookup method handles the access, and __getattr__ is reserved for cases where the attribute is genuinely missing.

Why this answer

In Python, when both __getattr__ and __getattribute__ are defined in a class, __getattribute__ is always called first for every attribute access. If the attribute exists in the instance (e.g., in the instance dictionary or via a descriptor), __getattribute__ returns it directly, and __getattr__ is never invoked. __getattr__ is only called as a fallback when __getattribute__ raises an AttributeError. Therefore, for an existing attribute, only __getattribute__ runs, making option D correct.

Exam trap

Python Institute often tests the misconception that __getattr__ is the primary hook for attribute access, when in fact __getattribute__ is always called first and __getattr__ is only a fallback for missing attributes.

How to eliminate wrong answers

Option A is wrong because __getattr__ does not override __getattribute__; rather, __getattribute__ takes precedence for all accesses, and __getattr__ is only a fallback for missing attributes. Option B is wrong because both methods are not called in order for an existing attribute; __getattribute__ returns the value immediately, so __getattr__ is not invoked at all. Option C is wrong because __getattr__ is not called when the attribute exists; it is only triggered when __getattribute__ raises an AttributeError.

265
MCQmedium

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

266
MCQeasy

A class MyClass defines __str__ and __repr__ methods. What is the purpose of __repr__?

A.To return a human-readable string for end users
B.To compare object equality
C.To return a hash value of the object
D.To return an unambiguous representation of the object, ideally for debugging
AnswerD

The canonical purpose of __repr__ is to return an unambiguous, developer-oriented string that is ideally a valid Python expression such that eval(repr(obj)) recreates the object. This makes it the primary tool for debugging and logging, where the exact type and state of an object matter more than polished presentation. It intentionally favors completeness and precision over the informal readability that __str__ provides.

Why this answer

The `__repr__` method is designed to return an unambiguous string representation of an object, ideally one that can be used to recreate the object or that clearly shows its internal state for debugging purposes. This is distinct from `__str__`, which targets end-user readability. The Python documentation explicitly states that `__repr__` should be unambiguous, while `__str__` should be readable.

Exam trap

The trap here is that candidates confuse `__repr__` with `__str__`, assuming both serve the same purpose, but The PCAP exam specifically tests that `__repr__` is for unambiguous debugging output, not user-friendly display.

How to eliminate wrong answers

Option A is wrong because returning a human-readable string for end users is the purpose of `__str__`, not `__repr__`. Option B is wrong because comparing object equality is handled by the `__eq__` method, not `__repr__`. Option C is wrong because returning a hash value is the job of the `__hash__` method, which is used for dictionary keys and set membership, not `__repr__`.

267
MCQhard

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

268
Drag & Dropmedium

Drag and drop the steps to debug a Python script using pdb into the correct order.

Drag or tap steps into the slots.

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

Why this order

Debugging with pdb involves setting a trace, running the script, using commands to step through code, setting breakpoints, and exiting.

269
MCQeasy

A developer wants to implement a read-only property for a class 'Temperature' that returns the temperature in Celsius but prevents external modification. Which code snippet correctly defines such a property?

A.class Temperature: @property def celsius(self): return self._celsius @celsius.setter def celsius(self, val): self._celsius = val
B.class Temperature: def __setattr__(self, name, val): if name == 'celsius': raise AttributeError
C.class Temperature: @property def celsius(self): return self._celsius
D.class Temperature: def __init__(self, c): self.celsius = c
AnswerC

This is the correct read-only property because it defines only a getter method via `@property`. With no setter, Python treats the property as read-only, and assigning to `celsius` raises `AttributeError`. Internal storage in `self._celsius` remains private, while the property exposes a controlled public interface.

Why this answer

It defines a read-only property using the `@property` decorator with only a getter method. Without a setter, any attempt to assign a value to `celsius` will raise an `AttributeError`, making the property read-only. This is the standard Pythonic way to implement a read-only attribute.

Exam trap

Python Institute often tests the misconception that a property without a setter is still writable by default, or that overriding `__setattr__` is a valid alternative to `@property` for creating a read-only attribute, but the correct approach is to omit the setter decorator entirely.

How to eliminate wrong answers

Option A is wrong because it includes a setter method (`@celsius.setter`), which allows external modification of the property, contradicting the requirement for a read-only property. Option B is wrong because overriding `__setattr__` to raise an `AttributeError` for the name 'celsius' would prevent setting the attribute even inside the class (e.g., in `__init__`), breaking normal initialization and not providing a proper property interface. Option D is wrong because it simply assigns `celsius` as a regular instance attribute in `__init__`, which is fully writable and does not use the `@property` decorator, so it is not a read-only property.

270
MCQmedium

A team is developing a system that must handle different types of documents (PDF, Word, etc.). Each document type has a unique parsing method. To avoid massive conditional logic, which OOP concept should be applied?

A.Polymorphism
B.Encapsulation
C.Inheritance
D.Abstraction
AnswerA

Polymorphism (specifically subtype polymorphism) is correct because it allows a common interface or base-class reference to invoke different implementations depending on the actual runtime type. In a system handling different types, a single method call can be dispatched dynamically to the appropriate subclass override, which directly addresses the need for type-specific behavior. This is the OOP feature specifically designed to let objects of different classes respond to the same message in distinct ways.

Why this answer

Polymorphism allows different document types (PDF, Word, etc.) to be treated uniformly through a common interface (e.g., a `parse()` method) while each class implements its own parsing logic. This eliminates the need for conditional statements (like `if type == 'PDF'`) because the correct method is resolved at runtime via dynamic dispatch, which is exactly what the team needs to avoid massive conditional logic.

Exam trap

Python Institute often tests the distinction between inheritance and polymorphism: candidates mistakenly think inheritance alone solves the problem, but without polymorphic method dispatch, you still need conditional logic to handle different types.

How to eliminate wrong answers

Option B (Encapsulation) is wrong because encapsulation focuses on bundling data and methods together and restricting direct access to internal state (e.g., via private attributes), not on avoiding conditional logic for different types. Option C (Inheritance) is wrong because while inheritance can share common code among document types, it does not by itself eliminate the need for conditionals; you would still need to check the object's type to call the correct parsing method without polymorphism. Option D (Abstraction) is wrong because abstraction hides implementation details behind an interface or abstract class, but without polymorphism you would still need conditional logic to decide which concrete implementation to invoke.

271
MCQmedium

Refer to the exhibit. Which of the following correctly shows the MRO of class D?

A.[D, B, C, A, object]
B.[D, A, B, C, object]
C.[D, B, A, C, object]
D.[D, C, B, A, object]
AnswerA

This is the exact output of C3 linearization for a diamond hierarchy where D inherits from B and C, and both B and C inherit from A. The merge step first takes D, then B because it is the head of the first base list and appears in no other list's tail, then C (not A, because A is in the tail of C's list), and finally A and object. This preserves both local precedence (B before C) and monotonicity (each base's own MRO is a subsequence of D's).

Why this answer

Python's Method Resolution Order (MRO) for class D, which inherits from B and C (where B inherits from A and C inherits from A), follows the C3 linearization algorithm. The MRO is computed as D -> B -> C -> A -> object, ensuring that each class appears before its parents and that the order respects the local precedence order of D's bases (B before C).

Exam trap

Python Institute often tests the C3 linearization rule that the local precedence order (the order of bases in the class definition) must be preserved, so candidates mistakenly reorder bases based on inheritance depth rather than the explicit left-to-right order in the class statement.

How to eliminate wrong answers

Option B is wrong because it places A before B and C, violating the local precedence order of D's bases (B, C) and the C3 algorithm's requirement that a parent class appears after all its subclasses. Option C is wrong because it places A before C, which breaks the monotonicity of the C3 linearization; since C inherits from A, A must come after C. Option D is wrong because it places C before B, ignoring the explicit order of bases in class D's definition (B then C), which the C3 algorithm respects as the local precedence order.

272
MCQeasy

A user entered a string ' Hello, World! '. Which expression returns 'Hello, World!'?

A.s.split()
B.s.strip()
C.s.rstrip()
D.s.lstrip()
AnswerB

strip() removes all leading and trailing whitespace characters — such as spaces, tabs, and newlines — and returns a new string with those characters removed. For "hello world", there are no surrounding whitespace characters, so it returns the exact same string unchanged. It leaves any internal whitespace intact, which is the desired behavior for trimming a string. This method is the standard and correct way to clean up whitespace at both ends of a string.

Why this answer

The `strip()` method removes all leading and trailing whitespace characters from a string, returning a new string without the surrounding spaces. In this case, `s.strip()` removes the three leading spaces and three trailing spaces from ' Hello, World! ', resulting in 'Hello, World!'.

Exam trap

Python Institute often tests the distinction between `strip()`, `lstrip()`, and `rstrip()` by presenting a string with both leading and trailing whitespace, tempting candidates to choose a partial removal method when only the full `strip()` works.

How to eliminate wrong answers

Option A is wrong because `split()` without arguments splits the string on any whitespace and returns a list of substrings, not a single string; it would produce ['Hello,', 'World!'] (or similar depending on whitespace). Option C is wrong because `rstrip()` only removes trailing whitespace, leaving the leading spaces intact, so it would return ' Hello, World!'. Option D is wrong because `lstrip()` only removes leading whitespace, leaving the trailing spaces intact, so it would return 'Hello, World! '.

273
Multi-Selecthard

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

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

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

Why this answer

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

Exam trap

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

274
Multi-Selecthard

Which THREE methods return a boolean value?

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

Returns True or False.

Why this answer

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

Exam trap

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

275
MCQmedium

A package 'tools' has the structure: tools/__init__.py, tools/calc.py, tools/io.py. In __init__.py, the developer writes: from . import calc. A user tries: import tools; print(tools.add(1,2)). This fails with AttributeError. Why?

A.The add function is not imported into the tools package namespace.
B.The function add is not defined in calc.py.
C.Relative imports are not allowed in __init__.py files.
D.The user should use tools.calc.add instead.
AnswerA

The AttributeError occurs because `__init__.py` only imports the `calc` module itself (e.g., via `from . import calc`), so the package namespace of `tools` contains the name `calc`, but not `add`. In Python, the attributes of a package are exactly the names bound in its `__init__.py`; importing a submodule does not automatically copy that submodule's functions into the package's top level. Thus `tools.add` is an undefined attribute, while `tools.calc.add` works.

Why this answer

The `__init__.py` file only imports the `calc` module itself into the `tools` package namespace, not the `add` function. When a user calls `tools.add(1,2)`, Python looks for `add` directly in the `tools` namespace, but it is not there — it is only accessible as `tools.calc.add`. The `from . import calc` statement binds the name `calc` to the module, not its contents.

Exam trap

Python Institute often tests the misconception that importing a submodule automatically makes its contents available at the package level, when in fact only the submodule name is added to the package namespace.

How to eliminate wrong answers

Option B is wrong because the question does not state that `add` is undefined in `calc.py`; the error is about namespace visibility, not definition. Option C is wrong because relative imports like `from . import calc` are perfectly allowed in `__init__.py` files — they are the standard way to expose submodules. Option D is wrong because while `tools.calc.add` would work, the question asks why the original call fails, not how to fix it; the failure is due to the missing import of `add` into the package namespace.

276
MCQmedium

A developer wants to ensure that a file is always closed after writing, even if an exception occurs. Which approach is considered best practice in Python?

A.Use try/finally with explicit f.close()
B.Rely on the garbage collector to close the file
C.Use try/except/finally with f.close() in both except and finally
D.Use the with statement: with open('file.txt', 'w') as f: ...
AnswerD

Using the with statement is the idiomatic Pythonic solution because it leverages the context manager protocol: open() returns a file object whose __enter__ and __exit__ methods are invoked by with, guaranteeing that __exit__ calls close() even if the body raises an exception or encounters a return/break/continue. This automatically flushes buffered writes and releases the OS file descriptor deterministically at the end of the block. It also handles the case where open() itself fails by never entering the block, so no file object needs cleanup, and it expresses the intent of scoped resource management clearly.

Why this answer

The `with` statement in Python implements a context manager that automatically calls the file's `__exit__` method, which closes the file even if an exception occurs inside the block. This is the idiomatic and recommended approach for resource management, as it guarantees cleanup without requiring explicit `close()` calls.

Exam trap

Python Institute often tests the misconception that `try/finally` with explicit `close()` is equivalent to the `with` statement, but the trap is that the `with` statement is the explicitly recommended best practice in the Python documentation and PEP 343, making it the correct answer over more manual approaches.

How to eliminate wrong answers

Option A is wrong because while `try/finally` with explicit `f.close()` does ensure the file is closed, it is more verbose and error-prone than the `with` statement, and it is not considered best practice in modern Python. Option B is wrong because relying on the garbage collector to close the file is unreliable — the garbage collector may not run immediately, and file descriptors are a limited OS resource that should be released deterministically. Option C is wrong because placing `f.close()` in both `except` and `finally` is redundant and unnecessary; the `finally` block alone guarantees execution regardless of exceptions, so duplicating the call in `except` adds no benefit and can lead to double-close errors if not handled carefully.

277
MCQmedium

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

278
MCQhard

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

279
MCQeasy

A developer defines a class with a private attribute `_value` and wants to provide controlled access. Which approach is the most Pythonic?

A.Use `__slots__` to restrict attribute creation.
B.Make `_value` public and rely on documentation.
C.Use @property to define getter and setter methods.
D.Define `get_value()` and `set_value()` methods.
AnswerC

Using the `@property` decorator is the canonical Pythonic way to encapsulate private attributes because it allows you to define getter and setter methods while preserving plain attribute syntax for callers. The getter can hide internal representation or perform lazy computation, and the setter can validate input before assigning to the underlying `_value`, ensuring invariants hold. This provides controlled access without forcing explicit method calls, striking the right balance between encapsulation and usability.

Why this answer

Using the `@property` decorator is the most Pythonic way to implement controlled access to a private attribute. It allows you to define getter and setter methods that can be called like regular attribute access (e.g., `obj.value`), preserving encapsulation while maintaining a clean, non-method-call interface. This approach aligns with Python's philosophy of 'we are all consenting adults' and avoids the verbosity of explicit getter/setter methods.

Exam trap

Python Institute often tests the distinction between Pythonic idioms and patterns borrowed from other languages (like Java), so the trap here is that candidates familiar with Java or C++ may choose Option D (explicit getter/setter methods) because it looks familiar, missing that Python's `@property` is the preferred, more concise approach.

How to eliminate wrong answers

Option A is wrong because `__slots__` is used to restrict the attributes that can be assigned to an instance, not to provide controlled access to a specific attribute; it does not define getters or setters. Option B is wrong because making `_value` public and relying on documentation violates encapsulation principles and provides no runtime enforcement or validation, which is not Pythonic for controlled access. Option D is wrong because defining `get_value()` and `set_value()` methods is a Java-style approach that is considered non-Pythonic; Python prefers the `@property` decorator for a more natural attribute-like syntax.

280
Multi-Selecthard

Which THREE of the following are characteristics of Python's special methods (dunder methods)? (Select exactly three.)

Select 3 answers
A.They enable operator overloading for user-defined classes.
B.They can be defined in a class to customize behavior.
C.Every class automatically has all special methods predefined.
D.They must be defined inside the class definition and cannot be added later.
E.They are automatically invoked by Python in certain contexts.
AnswersA, B, E

Special methods allow user-defined classes to redefine how operators such as +, -, ==, and < behave by implementing reserved dunder names like __add__, __eq__, or __lt__. When Python evaluates an expression like a + b, it dispatches to a.__add__(b) (or the reflected method on b if needed), enabling custom types to support the same syntactic sugar as built-in types. For example, a Vector class can define __add__ to perform element-wise addition, making v1 + v2 valid.

Why this answer

Special methods like `__add__` and `__eq__` allow user-defined classes to redefine the behavior of operators such as `+` and `==`. When Python encounters an operator expression, it looks up the corresponding dunder method on the object's class, enabling operator overloading in a clean, syntactic way.

Exam trap

Python Institute often tests the misconception that all dunder methods are automatically inherited or that they cannot be added dynamically, so candidates mistakenly select option C or D without realizing that Python's data model only provides defaults for a minimal set and allows runtime assignment to classes.

281
MCQhard

A developer writes a class `Logger` with a method `log(self, message)`. They want to ensure that when `Logger` is subclassed, any override of `log` must call the parent's `log` method. Which technique best enforces this requirement in Python?

A.There is no built-in Python mechanism to enforce that an override calls the parent method; it must be handled by convention and documentation.
B.Decorate the parent's `log` method with `@abstractmethod`.
C.Use a metaclass that wraps the `log` method to check if `super().log` was called.
D.Define `log` in the parent class to raise `NotImplementedError` and document that subclasses must call `super().log()`.
AnswerA

Python does not provide a built-in way to enforce that a subclass override calls the superclass method. This is by design, as Python relies on conventions and developer discipline. While design patterns like the template method can encourage it, they do not enforce it. The correct answer acknowledges this limitation.

Why this answer

Python's philosophy emphasizes flexibility and developer responsibility. There is no language-level construct that forces a subclass to call `super().log()`. Techniques like abstract methods ensure implementation but not invocation of the parent.

Metaclasses or descriptors could be used to add checks, but they are not built-in and are overly complex. The correct answer recognizes that enforcement is not a built-in feature.

Exam trap

The trap here is assuming that abstract methods or other decorators can enforce that a subclass calls the parent method, when they cannot.

282
MCQmedium

When processing a large text file, a developer notices that using str.replace() in a loop is slow. Which alternative is most efficient for multiple replacements?

A.Use str.maketrans() on the original string
B.Use re.sub() from the re module
C.Use str.translate() with a translation table
D.Chain multiple str.replace() calls
AnswerC

str.translate() with a translation table is correct because it replaces every character in a single C-level pass: each character's code point is looked up in the table and replaced with the designated string, or deleted if mapped to None, without constructing intermediate copies. The translation table is created once via str.maketrans() and reused for every line or chunk, so the total work is proportional to the file size rather than to the number of distinct replacements. This makes it the fastest built-in approach for bulk character-level substitutions in large text.

Why this answer

`str.translate()` with a translation table built by `str.maketrans()` performs all character replacements in a single pass over the string, operating at the C level in CPython. This avoids the O(n) per-replacement overhead of `str.replace()` in a loop, making it the most efficient choice for multiple, fixed-character substitutions on large text.

Exam trap

Python Institute often tests the misconception that `str.maketrans()` alone performs replacements, when in fact it only generates the table required by `str.translate()`, leading candidates to mistakenly select option A.

How to eliminate wrong answers

Option A is wrong because `str.maketrans()` only creates a translation table; it does not perform any replacement itself and must be used with `str.translate()` to be effective. Option B is wrong because `re.sub()` uses a regex engine that compiles patterns and backtracks, incurring significant overhead for simple, fixed-character replacements compared to a direct translation table. Option D is wrong because chaining multiple `str.replace()` calls processes the entire string multiple times (once per call), leading to O(n*m) complexity where m is the number of replacements, which is inefficient for large files.

283
MCQhard

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

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

Strings in Python are immutable, so indexed assignment raises TypeError: 'str' object does not support item assignment. The statement s[0] = 'x' attempts in-place mutation of an existing str object, which the type forbids; the interpreter rejects it at runtime rather than silently creating a new string.

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

284
Drag & Dropmedium

Drag and drop the steps to create a simple HTTP server using the http.server module in Python into the correct order.

Drag or tap steps into the slots.

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

Why this order

Creating an HTTP server involves importing http.server, defining a handler, overriding methods, creating an HTTPServer instance, and calling serve_forever().

285
Multi-Selecthard

Which THREE of the following are valid ways to create a string in Python?

Select 3 answers
A.'Hello"
B.'Hello'
C.f'{name}'
D.`Hello`
E.'''Hello'''
AnswersB, C, E

The literal 'Hello' is a standard single-quoted string, which is a perfectly valid way to create a string in Python. It uses a matching pair of single quote characters as delimiters, enclosing the sequence of characters exactly as written. Functionally, single-quoted strings are equivalent to double-quoted strings, though consistency in quoting style is a common best practice.

Why this answer

In Python, valid string literals can be enclosed in single quotes, double quotes, triple single quotes, or triple double quotes. Formatted string literals (f-strings) are also valid. Option A is invalid because it uses mismatched quote characters: it opens with a single quote but closes with a double quote.

Option B uses consistent single quotes. Option C is an f-string. Option D uses backticks, which are not valid Python string delimiters.

Option E uses triple single quotes, which are valid for multi-line strings.

Exam trap

Python Institute often tests the distinction between valid Python string delimiters and those from other languages, such as backticks, to catch candidates who confuse Python syntax with JavaScript or shell scripting.

286
MCQeasy

Which of the following expressions returns the string 'Hello' repeated three times?

A.'Hello' * 3
B.'Hello' + 3
C.'Hello' * '3'
D.'Hello' * 3.0
AnswerA

In Python, the * operator, when applied to a string and an integer, performs sequence repetition. Because 3 is an int, 'Hello' * 3 creates a new string by joining three sequential copies of the original 'Hello', yielding exactly 'HelloHelloHello'. This is valid string repetition that works for any string and any non-negative integer, and it returns a single string object, not a tuple or list.

Why this answer

In Python, the multiplication operator (*) when used with a string and an integer performs string repetition. 'Hello' * 3 returns the string 'HelloHelloHello' by concatenating three copies of the original string. This is a core feature of Python's sequence protocol, where strings are sequences of characters.

Exam trap

The trap here is that candidates may think the + operator can coerce types or that string multiplication accepts any numeric type, but Python strictly requires an integer for the repetition count and raises a TypeError for floats or strings.

How to eliminate wrong answers

Option B is wrong because the + operator cannot concatenate a string with an integer; it raises a TypeError: can only concatenate str (not 'int') to str. Option C is wrong because '3' is a string, not an integer; multiplying a string by a string raises a TypeError: can't multiply sequence by non-int of type 'str'. Option D is wrong because 3.0 is a float, not an integer; multiplying a string by a float raises a TypeError: can't multiply sequence by non-int of type 'float'.

287
MCQeasy

Which mode should be used when opening a file for writing such that new content is appended to the end without truncating existing content?

A.'x'
B.'r+'
C.'w'
D.'a'
AnswerD

The 'a' (append) mode opens the file for writing and places the file pointer at the end of the existing content, so every write extends the file without overwriting or truncating it. If the file is missing, Python creates a new empty file, matching the requirement to write new data while preserving what is already there. This is the only standard write mode designed specifically for adding to the end of a file.

Why this answer

('a') is correct because the 'a' mode opens a file for appending, which means new data is written to the end of the file without truncating any existing content. This is the standard behavior defined in Python's open() function for append mode.

Exam trap

Python Institute often tests the confusion between 'w' (which truncates) and 'a' (which appends), and candidates mistakenly choose 'w' thinking it simply writes without realizing it destroys existing data.

How to eliminate wrong answers

Option A ('x') is wrong because 'x' is exclusive creation mode — it opens a file for writing but fails if the file already exists, and it does not append. Option B ('r+') is wrong because 'r+' opens a file for both reading and writing, but it does not automatically position the write pointer at the end; it starts at the beginning and can overwrite existing content. Option C ('w') is wrong because 'w' opens a file for writing and truncates the file to zero length, destroying all existing content.

288
MCQeasy

Which expression returns the last character of string s?

A.s[-1]
B.s[len(s)]
C.s[-0]
D.s[0]
AnswerA

Python supports negative indices that count from the end of a sequence. An index of -1 specifically refers to the last element, so s[-1] evaluates to the final character of s, regardless of the string's length. Internally, Python converts negative indices by adding len(s), yielding len(s)-1, which is always the final valid position.

Why this answer

Python uses zero-based indexing for strings, where negative indices count from the end. s[-1] directly accesses the last character of the string, as -1 refers to the final element in the sequence.

Exam trap

The PCAP exam often tests the misconception that negative indexing starts at -0 or that len(s) is a valid index, leading candidates to pick s[len(s)] or s[-0] when they forget that indices are zero-based and negative indices count from -1 for the last element.

How to eliminate wrong answers

Option B is wrong because s[len(s)] raises an IndexError: string index out of range, since valid indices for a string of length n are 0 to n-1. Option C is wrong because s[-0] is equivalent to s[0], which returns the first character, not the last. Option D is wrong because s[0] returns the first character of the string, not the last.

289
Matchingmedium

Match each list method to its effect.

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

Concepts
Matches

Adds x to end

Appends elements from iterable

Inserts x at index i

Removes first occurrence of x

Removes and returns last item

Why these pairings

Common list methods: append adds an element to the end, extend adds all elements from an iterable, remove deletes the first occurrence of a value, pop removes an element by index, and sort arranges the list in ascending order by default.

290
Multi-Selecthard

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

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

Single quote escape.

Why this answer

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

Exam trap

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

291
MCQeasy

Which string method would you use to check if a string starts with a specified prefix?

A.start_with()
B.startswith()
C.beginswith()
D.startwithcase()
AnswerB

startswith() is the correct and documented Python string method for prefix detection. It returns True if the string begins with the specified prefix and False otherwise. It also accepts a tuple of prefixes to check multiple alternatives, and optional start and end parameters to limit the search range within the string.

Why this answer

The correct method to check if a string starts with a specified prefix in Python is `str.startswith()`. It returns `True` if the string begins with the given prefix, otherwise `False`. This method is part of the standard string methods in Python and is case-sensitive by default.

Exam trap

The PCAP exam often tests the exact method name spelling and punctuation, so the trap here is that candidates may confuse `startswith()` with the non-existent `start_with()` or `beginswith()` due to familiarity with other languages or naming conventions.

How to eliminate wrong answers

Option A is wrong because `start_with()` is not a valid Python string method; the correct method uses `startswith` without an underscore. Option C is wrong because `beginswith()` is not a Python string method; Python uses `startswith` for this functionality. Option D is wrong because `startwithcase()` does not exist; Python's `startswith` method does not have a case-insensitive variant built-in, though you can achieve case-insensitive behavior by converting both strings to the same case first.

292
MCQmedium

Consider the following class hierarchy: class A: def method(self): return 'A'; class B(A): pass; class C(A): def method(self): return 'C'; class D(B, C): pass. What is the output of D().method() according to Python's MRO?

A.'B'
B.TypeError
C.'A'
D.'C'
AnswerD

C is the correct answer because C's method() is the first matching attribute encountered when traversing the MRO of the instance. Attribute lookup checks each class's __dict__ in the order determined by the C3 linearization, and since C is more specialized than its bases, its method() takes precedence. The call therefore dispatches to C's implementation, and the returned string is 'C'.

Why this answer

Python's MRO (Method Resolution Order) for class D(B, C) is computed using the C3 linearization algorithm, which respects the local precedence order and monotonicity. The MRO for D is D -> B -> C -> A, so D().method() resolves to C.method(), returning 'C'. Option D is correct because C is the first class in the MRO that defines method().

Exam trap

Python Institute often tests the C3 linearization rule that the MRO respects the order of base classes in the class definition, so candidates mistakenly think B's inheritance from A takes precedence over C's override, leading them to pick 'A' or 'B' instead of 'C'.

How to eliminate wrong answers

Option A is wrong because 'B' is not returned; class B does not override method(), so the MRO proceeds to C before reaching A. Option B is wrong because no TypeError occurs; the MRO is well-defined and method() is found in class C. Option C is wrong because 'A' is not returned; although A defines method(), the MRO finds C's override first, so A's version is never called.

293
MCQmedium

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

294
MCQeasy

A developer writes a script that reads a configuration file. If the file does not exist, the program should print an error and continue. Which code snippet correctly implements this behavior?

A.try: open('config.txt') except FileNotFoundError: print('File not found')
B.f = open('config.txt', 'r') if not f: print('File not found')
C.try: f = open('config.txt') except: print('File not found')
D.try: with open('config.txt') as f: pass except Exception: print('File not found')
AnswerA

This snippet is correct because it confines the error handling to exactly the condition the developer cares about: the file's absence. When the interpreter evaluates open('config.txt'), a missing config file raises a FileNotFoundError (a subclass of OSError), and that exception is caught and handled specifically. Other I/O problems, such as a permission denial or a path that is actually a directory, raise different OSError subclasses and are allowed to propagate, which preserves diagnostic accuracy.

Why this answer

It uses a `try` block to attempt opening the file and catches only `FileNotFoundError`, which is the specific exception raised when the file does not exist. This allows the program to print an error and continue execution without crashing, precisely matching the requirement.

Exam trap

Python Institute often tests the distinction between catching a specific exception versus a broad or bare `except`, and the trap here is that candidates may think any `try-except` works, overlooking the requirement to catch only `FileNotFoundError` for precise error handling.

How to eliminate wrong answers

Option B is wrong because `open()` does not return a falsy value when the file is missing; it raises a `FileNotFoundError` before any assignment occurs, so the `if not f` check is never reached. Option C is wrong because it uses a bare `except:` clause, which catches all exceptions (including unrelated ones like `KeyboardInterrupt` or `PermissionError`), violating best practices and potentially masking bugs. Option D is wrong because it catches the overly broad `Exception` class, which is too general and could hide unexpected errors; the requirement specifically needs to catch only `FileNotFoundError`.

295
MCQhard

Refer to the exhibit. What does the 'from None' clause do in the second raise statement?

A.It causes the original exception to be ignored.
B.It prevents chaining of exceptions, so only the final exception is displayed.
C.It causes both exceptions to be raised simultaneously.
D.It replaces the original exception with a new one.
AnswerB

When you write `raise NewException from None`, Python's exception-handling machinery sets `__suppress_context__ = True` on the new exception. This disables the automatic chaining that normally links the current exception to the one that was being handled, which would otherwise show as "During handling of the above exception, another exception occurred" in the traceback. As a result, only the final exception's traceback is displayed, and the original, caught exception is not shown as context, though it still exists internally.

Why this answer

In Python, the 'from None' clause in a raise statement explicitly suppresses exception chaining. Normally, when an exception is raised inside an except block, Python automatically chains the new exception to the original one using the __cause__ attribute. Using 'raise NewException from None' sets __cause__ to None, which prevents the interpreter from displaying the original exception's traceback, so only the final exception is shown.

Exam trap

The PCAP exam often tests the distinction between suppressing chaining ('from None') and replacing or ignoring the original exception, leading candidates to mistakenly think the original exception is lost or ignored entirely.

How to eliminate wrong answers

Option A is wrong because 'from None' does not ignore the original exception; the original exception still occurs and can be accessed programmatically, but its traceback is suppressed. Option C is wrong because Python does not support raising two exceptions simultaneously; 'from None' only controls chaining, not concurrent raising. Option D is wrong because 'from None' does not replace the original exception; it merely prevents the automatic chaining that would display the original exception's context.

296
MCQmedium

Inside a package 'data', there is a subpackage 'io' and a module 'utils'. Which import statement inside the 'io' subpackage correctly imports the 'helper' function from the sibling module 'utils'?

A.from ..utils import helper
B.import data.utils.helper
C.from .utils import helper
D.from data.io.utils import helper
AnswerA

Correct. The leading `..` is a relative import that ascends one level from the current subpackage `data.io` to the parent package `data`, then enters the sibling `utils` subpackage/module, from which `helper` is imported. This is the proper PEP 328 syntax for referring to a sibling in a package hierarchy, and it works regardless of the top-level package's absolute location on `sys.path`.

Why this answer

The `..` prefix in a relative import refers to the parent package (`data`), and then `utils` is a sibling module of `io` within that parent package. This allows the `io` subpackage to import the `helper` function from the sibling module `utils` using `from ..utils import helper`.

Exam trap

Python Institute often tests the distinction between a single dot (`.` for same-package siblings) and double dots (`..` for parent-package siblings), causing candidates to mistakenly use `from .utils import helper` when the target module is in the parent package, not the current one.

How to eliminate wrong answers

Option B is wrong because `import data.utils.helper` is an absolute import that attempts to import a function directly, but Python requires importing the module first (e.g., `from data.utils import helper`). Option C is wrong because `from .utils import helper` uses a single dot, which refers to the current package (`data.io`), but there is no `utils` module inside `io`; it is a sibling, not a child. Option D is wrong because `from data.io.utils import helper` implies `utils` is a subpackage of `io`, but the problem states `utils` is a sibling module at the `data` package level, not inside `io`.

297
MCQhard

Which of the following exception classes is NOT a direct subclass of Exception in Python?

A.IOError
B.SystemExit
C.StopIteration
D.ValueError
AnswerB

SystemExit is the correct answer because it inherits directly from BaseException rather than from Exception. Unlike IOError, StopIteration, and ValueError—all of which are descendants of Exception—SystemExit bypasses the Exception class entirely. This deliberate design lets SystemExit (along with KeyboardInterrupt) propagate even when code catches Exception, so it is the only listed class that is not a subclass of Exception.

Why this answer

SystemExit is not a direct subclass of Exception; it inherits from BaseException instead. This is because SystemExit, along with KeyboardInterrupt and GeneratorExit, is intended to signal that the interpreter should exit, and catching it with a generic except Exception clause would be inappropriate. All other options (IOError, StopIteration, ValueError) are direct subclasses of Exception.

Exam trap

Python Institute often tests the distinction between BaseException and Exception, trapping candidates who assume all built-in exceptions inherit from Exception, when in fact SystemExit, KeyboardInterrupt, and GeneratorExit are direct subclasses of BaseException.

How to eliminate wrong answers

Option A is wrong because IOError is a direct subclass of Exception (and in Python 3, it is an alias of OSError, which also inherits from Exception). Option C is wrong because StopIteration is a direct subclass of Exception, used to signal the end of an iterator. Option D is wrong because ValueError is a direct subclass of Exception, raised when a built-in operation or function receives an argument with the right type but an inappropriate value.

298
MCQeasy

Refer to the exhibit. If the file config.cfg exists but the user does not have read permission, what will be printed?

A.An unhandled exception is raised
B.'Permission denied'
C.Nothing; the program continues silently
D.'File not found'
AnswerB

Since config.cfg exists but the process lacks the required read permission, the file's opening operation raises `PermissionError`. The corresponding `except PermissionError` clause catches it and executes its print statement, producing `'Permission denied'` as the program's visible output. This is the expected, handled outcome.

Why this answer

When `open()` is called on a file that exists but the user lacks read permission, Python raises a `PermissionError`. Since no exception handling is present, the exception is unhandled and Python prints a traceback to stderr which includes the error message `'Permission denied'` (among other details). Option B correctly identifies the permission-denied message that appears in the output.

Exam trap

Python Institute often tests the distinction between file existence errors (FileNotFoundError) and permission errors (PermissionError), and candidates mistakenly assume that a missing file is the only possible file-related exception.

How to eliminate wrong answers

Option A is wrong because an unhandled exception is indeed raised, but the question asks what will be printed — the exception's error message ('Permission denied') is printed, not just an unhandled exception without output. Option C is wrong because Python does not silently continue when a file permission error occurs; it raises an exception that must be caught to avoid termination. Option D is wrong because the file config.cfg exists (as stated in the question), so a 'File not found' error would only occur if the file did not exist, which is not the case here.

299
MCQmedium

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

300
MCQhard

What is the result of the expression '123'.zfill(5)?

A.'00123'
B.'123'
C.'000123'
D.'12300'
AnswerA

zfill(5) pads the string '123' with ASCII zero characters on the left until the total length reaches the specified width. Because '123' has length 3 and the target width is 5, exactly 2 zeros must be prepended, yielding '00123'. This is the documented behavior and the only correct result.

Why this answer

The `zfill()` method in Python pads the string on the left with zeros until it reaches the specified width. For the string '123' and width 5, it adds two zeros to the left, resulting in '00123'. This is the correct behavior as defined in Python's string methods.

Exam trap

Python Institute often tests the misconception that `zfill()` pads zeros on the right or that the width includes the original string length plus padding, leading candidates to choose options like '000123' or '12300'.

How to eliminate wrong answers

Option B is wrong because it represents the original string without any padding, ignoring the width parameter of 5. Option C is wrong because it adds three zeros, which would be the result for width 6, not 5. Option D is wrong because it pads zeros on the right, but `zfill()` always pads on the left, not the right.

Page 3

Page 4 of 6

Page 5

All pages