Python Institute · Free Practice Questions · Last reviewed May 2026
24real exam-style questions organised by domain, each with the correct answer highlighted and a plain-English explanation of why it's right — and why the others are wrong.
34% of exam · 6 sample questions below
A developer creates a Python class with a method that is intended to be overridden in subclasses. Which approach best ensures that the method is not accidentally called on the base class?
Use 'pass' as the method body
Delete the method from the base class using 'del'
Add a comment '# override in subclass' inside the method body
Raise NotImplementedError inside the method body
Raising NotImplementedError in the base method body makes any direct call fail immediately at runtime, forcing subclasses to provide their own implementation. This satisfies the stem's requirement that the method is not accidentally invoked on the base class.
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?
Use a property decorator on a class method
Define a public class attribute and document it as read-only
Define an instance attribute inside __init__
Define a private class attribute (e.g., __shared) and provide a class method to access it
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.
A Python class 'BankAccount' has a method 'withdraw(amount)' that deducts 'amount' from 'self.balance'. A developer writes a subclass 'SavingsAccount' that overrides 'withdraw' to add a penalty if balance drops below minimum. Which design pattern is being used?
Composition
Aggregation
Method overriding
SavingsAccount redefines the inherited withdraw method with its own penalty logic while keeping the same signature, so Python dispatches to the subclass version at runtime. That substitution of a superclass method implementation is method overriding, not overloading or composition.
Inheritance
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?
Polymorphism
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.
Encapsulation
Inheritance
Abstraction
A developer writes a class 'Logger' with a class method 'log(msg)' that writes to a file. Another class 'AppLogger' inherits from 'Logger'. The developer expects both classes to share the same file handle. However, after creating an instance of 'AppLogger', the file handle is different. What is the most likely cause?
The 'log' method is defined as a class method using @classmethod
The file handle is opened in the __init__ method of the base class
Opening the file handle inside __init__ assigns the result to an instance attribute (via self), so each time a new Logger or subclass object is created, a separate descriptor is opened and stored on that specific instance. Because the handle is not attached to the class object, no sharing occurs between instances. This directly contradicts the premise that a single logger's file handle is shared, making this the correct flaw in the developer's code.
The file handle is stored as a private attribute __file
The subclass overrides the 'log' method
A class 'MyClass' has a method 'do_something' that uses 'self.__private'. A subclass 'MySubClass' tries to access 'self.__private' and gets an AttributeError. Why?
Because the attribute is defined as a class attribute, not instance attribute
Because the subclass overrides the method that uses the attribute
Because name mangling renames the attribute to _MyClass__private, and the subclass implicitly accesses _MySubClass__private
In Python, any attribute name written with two leading underscores inside class MyClass is transformed at compile time to _MyClass__private, a process called name mangling. When the same spelling __private appears in the body of a subclass, the compiler uses the subclass's name, producing _MySubClass__private; since that attribute was never assigned, self.__private raises AttributeError. The base class value still exists, but only under the base-mangled key _MyClass__private.
Because the attribute is private and not inherited
Want more Object-Oriented Programming practice?
Practice this domain12% of exam · 6 sample questions below
A developer is working on a project that requires the use of a third-party package hosted on a private repository. The developer wants to ensure that the package can be imported without specifying the full repository URL each time. Which approach should be taken?
Append the repository path to sys.path in the script.
Place the package files in the site-packages directory manually.
Configure the repository URL in pip's configuration file or in requirements.txt.
This is the standard, reproducible way to make Python's packaging tooling use a private or alternate repository: specify an index URL via index-url or extra-index-url in pip.conf, or use a fully-qualified requirement line (e.g., --extra-index-url) in requirements.txt. During installation, pip queries the configured indexes, resolves the complete dependency graph, and installs the package plus all of its dependencies into site-packages as wheel or sdist distributions. This method respects version constraints, generates proper distribution metadata, and works consistently across environments because the configuration is declarative and versionable.
Use os.system to run a pip install command from within the script.
A Python script imports the module 'my_module'. The developer wants to ensure that when the script is run directly, it executes a specific function, but when imported as a module, that function is not executed. Which code snippet achieves this?
if __name__ == '__main__': run()
This is the canonical Python idiom for conditional execution. The interpreter assigns the special variable __name__ the value '__main__' only when the source file is run directly as the main program (e.g., `python my_module.py`). When the file is imported as a module, __name__ becomes the module's fully qualified name, so the equality check fails and run() is not invoked, allowing safe import without side effects.
if __name__ == '__main__': run()
This option is exactly equivalent to the standard guard in option A, and it is just as correct. Comparing `__name__` to the string literal '__main__' is the recognized, PEP 8-compliant way to determine whether a file has been executed directly rather than imported. The identical code appearing twice in the options does not change its validity; both instances pass because the interpreter sets __name__ consistently regardless of how many times the idiom appears.
if os.environ.get('RUN_MAIN'): run()
if sys.argv[0] == 'my_module': run()
A developer is troubleshooting an ImportError: 'No module named 'config''. The config module is located in a subdirectory 'utils' relative to the script. The script's current working directory is the parent of 'utils'. Which of the following lines, added to the script, will resolve the issue?
sys.path.append('utils/config.py')
sys.path.append('utils')
This is the correct fix because sys.path is a list of directories Python searches when resolving import statements. Appending 'utils' adds that directory to the end of the list, making any Python module or package inside it visible to the import system. Since the target module lives directly in utils, adding this directory allows 'import config' or a similarly named module to be found.
sys.path = os.path.join(sys.path, 'utils')
os.chdir('utils')
A developer wants to import a specific function 'calculate' from a module named 'formulas' without importing the entire module. Which import statement should be used?
import formulas
import calculate from formulas
from formulas import calculate
This is the correct and idiomatic way to import exactly one function from a module. It binds the name `calculate` directly in the current namespace, so you can call `calculate(...)` without a module prefix, and it avoids pulling in the entire `formulas` module as a separate local name. This form also makes the dependency explicit, which improves readability and reduces the risk of accidentally shadowing other names.
import formulas as f
A developer notices that a custom package 'mypackage' is not being found when importing, even though it is installed in the site-packages directory. The developer suspects a conflict with another package of the same name. Which command should the developer run to diagnose the location from which Python is importing the package?
print(mypackage)
print(__file__)
print(mypackage.__file__)
For an imported module, the `__file__` attribute stores the filesystem path of the source file from which the module was loaded. When `mypackage` is a package, its `__file__` points to the package's `__init__.py` file, which is exactly the location of the package on disk in most ordinary cases. This is the standard, programmatic way to determine where a package or module resides, making this option correct.
import os; print(os.getcwd())
Which THREE of the following statements about Python packages and modules are true?
The sys.path list is read-only and cannot be modified at runtime.
A package must contain an __init__.py file to be importable.
A module is a single .py file containing Python definitions and statements.
This is the definition of a module.
The __all__ variable defines the public API of a module or package.
__all__ controls what is exported with 'from module import *'.
Relative imports use dots to refer to the current and parent packages.
A single dot refers to current package, two dots to parent, etc.
Want more Modules and Packages practice?
Practice this domain36% of exam · 6 sample questions below
A developer writes a function that reads a configuration file and returns its contents as a string. The file might not exist. Which exception should be caught to handle a missing file?
FileNotFoundError
FileNotFoundError is a built-in exception raised when a file or directory is requested but cannot be found at the specified path. It is a subclass of OSError and is specifically designed for missing-file scenarios, which is exactly the case when reading a configuration file that does not exist. In Python 3, it is the canonical exception for this situation, replacing the more generic IOError that was used in earlier versions.
PermissionError
IOError
OSError
Which of the following is the correct way to open a file for writing in text mode, ensuring that if the file already exists it will be overwritten?
open('file.txt', 'x')
open('file.txt', 'w')
The 'w' mode opens the file for writing and truncates it to zero bytes if it exists, or creates a new file if it does not. This makes it the standard choice for write operations that should replace the entire contents of the file. It is the correct mode here because it permits immediate writing to the file with the expectation that prior content will be discarded.
open('file.txt', 'r+')
open('file.txt', 'a')
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?
f.read(4)
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.
f.seek(4)
f.readline()
f.read()
Consider the following code snippet:
try:
x = int(input()) y = 10 / x
print(y)
except ZeroDivisionError:
print('Division by zero')except ValueError:
print('Invalid integer')If the user enters '0', what is the output?
No output
Both 'Invalid integer' and 'Division by zero'
Division by zero
When the user enters '0', int('0') returns 0 without error, so the try block proceeds to evaluate 10 / 0. This expression raises ZeroDivisionError, and Python matches it to the except ZeroDivisionError clause, causing 'Division by zero' to be printed. The output is exactly that message, demonstrating that an exception raised by an arithmetic operation is handled by its specific handler.
Invalid integer
Which of the following statements about the `finally` block is true?
It executes only if no exception is raised.
It does not execute if a return statement is in try block.
It executes only if an exception is raised.
It always executes, regardless of exceptions.
The `finally` block guarantees execution after the `try` block completes, whether an exception is raised, caught, or the block exits via `return`, `break` or `continue`. This satisfies the stem's requirement for a statement that is always true, since only `finally` provides unconditional cleanup semantics in Python.
A programmer wants to catch both `FileNotFoundError` and `PermissionError` with a single except clause. Which tuple is correct?
except (FileNotFoundError, PermissionError):
Correct syntax: parentheses form a tuple listing the two exception classes to catch. Python checks the raised exception against each class in the tuple and handles either FileNotFoundError or PermissionError in the same block. Because both derive from OSError, using this tuple is more precise than catching the parent class and avoids masking unrelated OSError subclasses.
except FileNotFoundError, PermissionError:
except OSError:
except [FileNotFoundError, PermissionError]:
Want more Exceptions and File I/O practice?
Practice this domainA developer needs to count the number of occurrences of the substring 'is' in the string 'This is a test. Is this a test?'. Which code correctly performs the count?
'This is a test. Is this a test?'.split().count('is')
'This is a test. Is this a test?'.count('is')
Correctly counts overlapping? No, count does not count overlapping, but 'is' appears at positions 5 and 17, not overlapping, so returns 2.
'This is a test. Is this a test?'.index('is')
'This is a test. Is this a test?'.find('is')
A programmer writes a function to check if a string is a palindrome (ignoring case and non-alphanumeric characters). Which implementation correctly achieves this?
def is_pal(s): s = s.lower(); return s == ''.join(reversed(s))
def is_pal(s): s = ''.join(c for c in s if c.isalnum()).lower(); return s == s[::-1]
This is the correct palindrome checker because it first strips out every non-alphanumeric character with a generator expression and ''.join(), then lowercases the cleaned string. Comparing this normalized form to its extended-slice reverse s[::-1] accounts for spaces, punctuation, and mixed case in one clean pass. This is the robust, idiomatic approach expected for a general-purpose palindrome test.
def is_pal(s): return s == s[::-1]
def is_pal(s): s = s.lower(); return s == s[::-1]
Which string method can be used to check if a string contains only digits?
str.isdigit()
str.isdigit() returns True only when the string is non-empty and every character has the Unicode Numeric_Type of Digit or Decimal, which includes ASCII '0'-'9', non-Arabic decimal digits, and compatibility superscripts such as '²'. This is the broadest check that still excludes letters, punctuation, and numeric fractions, so it is the correct method when the requirement is to verify that a string contains only digits.
str.isalnum()
str.isdecimal()
str.isnumeric()
A developer needs to replace all occurrences of 'cat' with 'dog' in a string, but only if 'cat' is a whole word (not part of 'category'). Which code achieves this?
re.sub(r'\bcat\b', 'dog', s)
The correct solution uses a raw-string regex pattern with word boundary anchors: `\b` at both ends ensures `cat` is only matched as a standalone word, not as a substring inside larger words like `category` or `bobcat`. `re.sub` then replaces every such whole-word occurrence globally, returning a new string with each standalone `cat` changed to `dog`, leaving all other text intact.
s.replace('cat', 'dog')
re.sub('cat', 'dog', s)
s.replace('cat', 'dog', 1)
What is the result of 'Python'.find('th')?
1
-1
2
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.
0
Which THREE are valid ways to create a multiline string in Python?
s = ('Line1\n' 'Line2')
This is correct because Python implicitly concatenates adjacent string literals at compile time. The expression ('Line1\n' 'Line2') produces the single string 'Line1\nLine2', where \n is a single escape character representing a line break. When printed, the result appears on two lines, so it is a valid multiline string. The parentheses are not required but help break long lines for readability.
s = """Line1 Line2"""
This is correct because triple double quotes, like triple single quotes, let a string span multiple physical source lines while preserving the embedded line breaks exactly as typed. The resulting string contains a newline character at the end of the first line, so it behaves as a genuine multiline string. This syntax is the standard choice for docstrings and is also convenient for writing SQL or long formatted text blocks in code.
s = '''Line1 Line2'''
This is correct because triple single quotes allow a string literal to contain literal newline characters, meaning the physical line break between Line1 and Line2 is preserved as part of the string value. It is equivalent to writing 'Line1\nLine2' but is more readable when the string is long. Additionally, triple single quotes permit embedded single quotes without escaping, giving it flexibility for multiline text.
s = "Line1\ Line2"
s = 'Line1 Line2'
Want more Strings practice?
Practice this domainThe PCAP exam has 40 questions and must be completed in 65 minutes. The passing score is 700/1000.
Scenario-based questions covering exam objectives with detailed answer explanations.
The exam covers 4 domains: Object-Oriented Programming, Modules and Packages, Exceptions and File I/O, Strings. Questions are weighted by domain — higher-weight domains appear more on your actual exam.
No. These are original exam-style practice questions written against the official Python Institute PCAP exam objectives. They are not copied from the real exam. Courseiva focuses on genuine understanding, not memorisation of braindumps.
Courseiva tracks your accuracy per domain and routes you toward weak areas automatically. Free, no account required.