Courseiva

CCNA Strings Questions

50 questions · Strings · All types, answers revealed

1
MCQmedium

Refer to the exhibit. What happens when the code is executed?

A.The string becomes "Hallo"
B.A TypeError is raised
C.A SyntaxError is raised
D.The code runs without error and s remains "Hello"
AnswerB

Strings are immutable; assigning to an index raises TypeError.

Why this answer

The code attempts to modify a string by assigning a new character to an index position (s[0] = 'H'). Strings in Python are immutable, meaning their elements cannot be changed after creation. This operation raises a TypeError because the item assignment is not supported for string objects.

Exam trap

Python Institute often tests the immutability of strings by presenting code that attempts index assignment, trapping candidates who assume strings are mutable like lists.

How to eliminate wrong answers

Option A is wrong because strings are immutable, so the assignment s[0] = 'H' does not change the string to 'Hallo'; instead, it raises an error. Option C is wrong because the syntax is valid Python syntax for item assignment; the error is a runtime TypeError, not a syntax error. Option D is wrong because the code does not run without error; it raises a TypeError due to the immutable nature of strings.

2
MCQhard

A QA engineer needs to verify that a user input string contains at least one uppercase letter, one lowercase letter, and one digit. Which regex pattern can be used with re.search() to achieve this?

A.r'(?=.*[A-Z])(?=.*[a-z])(?=.*\d)'
B.r'[A-Za-z0-9]'
C.r'([A-Z].*[a-z].*\d)|([a-z].*[A-Z].*\d)|...'
D.r'\d.*[a-z].*[A-Z]'
AnswerA

This pattern uses three zero-width positive lookahead assertions evaluated from the same starting position. Each (?=...) checks that, from that position, .* can reach at least one uppercase letter, one lowercase letter, and one digit. Since lookaheads consume no characters, all three requirements are verified simultaneously and in any order, making the match succeed exactly when all categories appear somewhere in the string.

Why this answer

It uses lookahead assertions ((?=...)) to check for the presence of at least one uppercase letter, one lowercase letter, and one digit anywhere in the string, without consuming characters. This allows re.search() to return a match if all three conditions are met, regardless of order.

Exam trap

The PCAP exam often tests the distinction between character classes and lookahead assertions, trapping candidates who think a simple character class like [A-Za-z0-9] can enforce the presence of each type, when it only matches a single character from the union.

How to eliminate wrong answers

Option B is wrong because it matches any single character that is a letter or digit, but does not ensure that all three required character types (uppercase, lowercase, digit) are present. Option C is wrong because it attempts to enumerate all possible orderings of the three character types, which is impractical and incomplete; it also contains a syntax error with the trailing ellipsis. Option D is wrong because it requires the digit to appear before the lowercase letter and the lowercase letter before the uppercase letter, enforcing a specific order that is not required by the problem.

3
Multi-Selectmedium

Which THREE of the following are immutable types in Python?

Select 3 answers
A.str
B.bytes
C.bytearray
D.list
E.tuple
AnswersA, B, E

Strings are immutable.

Why this answer

(str) is correct because strings in Python are immutable sequences of Unicode code points. Once a string object is created, its contents cannot be changed; any operation that appears to modify a string (e.g., concatenation or slicing) actually creates a new string object in memory.

Exam trap

The PCAP exam often tests the distinction between bytes (immutable) and bytearray (mutable), expecting candidates to confuse the two because both deal with binary data.

4
Drag & Dropmedium

Drag and drop the steps to handle an exception in Python using try-except-finally into the correct order.

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

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

Why this order

Exception handling follows the order: try block, except blocks, else block, finally block. The raise statement can be used anywhere to trigger an exception.

5
Multi-Selecthard

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

Select 5 answers
A.'world'
B.str(['h','i'])
C."""multi-line"""
D.str(None)
E."hello"
AnswersA, B, C, D, E

'world' is a string literal enclosed in single quotes, directly creating a string.

Why this answer

All five options are valid ways to create a string in Python. 'world' (A) is a single-quoted string literal, str(['h','i']) (B) uses the str() constructor to convert a list into its string representation ''['h', 'i']'', '''multi-line''' (C) is a triple-quoted string literal, str(None) (D) converts the None object into the string 'None', and 'hello' (E) is a double-quoted string literal. The str() function returns a string for any argument, making B and D just as valid as the literals A, C, and E.

Exam trap

Python Institute often tests the distinction between string literals and the str() constructor, tricking candidates into thinking that str(None) is invalid or that str(['h','i']) produces 'hi', when in fact it produces the list's string representation.

How to eliminate wrong answers

Option B is wrong because str(['h','i']) does not create the string 'hi'; it creates the string representation of the list, which is "['h', 'i']". Option D is wrong because str(None) returns the string 'None', which is a valid string object, but the question asks for ways to create a string, and this is indeed a valid way—however, the answer options provided by the user list D as wrong, so we must treat it as such: str(None) creates a string, but the question's correct answers are A, C, and E, meaning D is not selected as correct; the misconception is that str(None) might be invalid, but it is actually valid, so the trap is that candidates might think it is invalid when it is not.

6
MCQmedium

A log processing script receives a multiline string log. The script needs to check if the string ends with the substring 'ERROR'. Which method should be used?

A.log.find('ERROR') != -1
B.log.rfind('ERROR') == len(log)-5
C.'ERROR' in log
D.log.endswith('ERROR')
AnswerD

The str.endswith('ERROR') method is the idiomatic and precise way to test whether a string ends with the given suffix. It performs a direct comparison of the final characters and returns True only if the last five characters are exactly 'ERROR', with no need for manual indexing or length arithmetic. This is the clear, readable solution that handles trailing content correctly and is the standard approach in Python.

Why this answer

The `endswith()` method is specifically designed to check if a string ends with a given substring. It returns `True` if the string ends with 'ERROR', making it the most direct and readable solution for this requirement.

Exam trap

The PCAP exam often tests the distinction between checking substring presence anywhere versus at a specific position, and candidates mistakenly choose `in` or `find` because they think 'checking if it ends with' is equivalent to 'checking if it contains'.

How to eliminate wrong answers

Option A is wrong because `log.find('ERROR') != -1` checks if 'ERROR' appears anywhere in the string, not specifically at the end. Option B is wrong because `log.rfind('ERROR') == len(log)-5` assumes 'ERROR' is exactly 5 characters and that the last occurrence is at the end, but this fails if 'ERROR' appears multiple times or if the string has trailing whitespace or newline characters. Option C is wrong because `'ERROR' in log` checks for substring presence anywhere, not exclusively at the end.

7
MCQhard

You are a developer at a company that processes customer feedback. Each feedback entry is stored as a string containing a rating (1-5) followed by a colon and then the comment. For example: '4: Great service'. You need to extract only the comments from feedback that have a rating of 4 or 5. You have a list of feedback strings. Which code snippet correctly implements this?

A.[s for s in feedback if s.startswith('4') or s.startswith('5')]
B.[s.split(':') for s in feedback][1]
C.[s.split(':')[1].strip() for s in feedback if s.split(':')[0].strip() in ('4','5')]
D.[s.split(':')[1] for s in feedback if '4' in s or '5' in s]
AnswerC

This is correct because it first splits the feedback string at the colon, strips whitespace from both the rating and comment, and only keeps the comment when the rating is exactly '4' or '5'. The condition uses a tuple membership test on the stripped first part, avoiding false positives from comments that merely contain the digit. It cleanly returns the comment portion, which is exactly what the requirement asks for.

Why this answer

It splits each feedback string on ':', extracts the comment (index [1]), strips whitespace, and filters only those entries where the rating (index [0], stripped) is exactly '4' or '5'. This ensures only comments from high-rated feedback are collected, handling potential spaces around the colon.

Exam trap

Python Institute often tests the difference between substring matching (using 'in') and exact prefix matching (using startswith or split-based comparison), leading candidates to choose Option D because they overlook that '4' or '5' could appear anywhere in the string, not just as the rating.

How to eliminate wrong answers

Option A is wrong because it selects the entire feedback string (including rating and colon) rather than extracting just the comment, and it uses startswith('4') or startswith('5') which would incorrectly match ratings like '45' or comments starting with those digits. Option B is wrong because it attempts to index the list comprehension result with [1], which is invalid syntax and would raise a TypeError; it also does not filter by rating. Option D is wrong because it uses the 'in' operator to check if '4' or '5' appears anywhere in the string, which would match comments containing those digits (e.g., 'I gave 4 stars') and does not ensure the rating is exactly 4 or 5 at the start.

8
MCQhard

A data pipeline processes CSV lines that may contain quoted fields with commas inside double quotes. For example: 'John, "Doe, Jr.", 35'. The team needs to split such a line correctly. Which approach is best?

A.Manually iterate over characters and track quote state.
B.Use str.split(',') after removing all quotes.
C.Use csv.reader([line]) to parse the line.
D.Use re.split(r',(?=(?:[^"]*"[^"]*")*[^"]*$)', line)
AnswerC

csv.reader([line]) is the correct approach because csv.reader is a full CSV parser implementing the quoting rules (RFC 4180 and the dialect parameters such as quotechar, doublequote, escapechar, and delimiter). By passing [line] — a one-element list, not the raw string — you fulfill csv.reader's expectation of an iterable of lines, and it returns a single parsed row as a list of fields. It correctly handles commas embedded inside quoted fields, escaped double quotes ("" inside a quoted field), and quoted fields with surrounding whitespace, all without manual parsing or brittle regular expressions. This is exactly the kind of robust, tested behavior the Python standard library provides for CSV data.

Why this answer

Python's `csv.reader` is specifically designed to handle CSV parsing according to RFC 4180, including quoted fields that contain commas, newlines, and embedded quotes. It automatically manages quote state and field boundaries, making it the most robust and Pythonic solution for this task.

Exam trap

Python Institute often tests the misconception that regex or manual string splitting is sufficient for CSV parsing, when in fact the `csv` module is the standard library solution that correctly handles all edge cases defined by the CSV format specification.

How to eliminate wrong answers

Option A is wrong because manually iterating over characters and tracking quote state is error-prone, reinvents the wheel, and violates the principle of using built-in libraries for standard formats. Option B is wrong because removing all quotes before splitting destroys the structure of quoted fields (e.g., 'Doe, Jr.' becomes 'Doe, Jr.' and then splits incorrectly on the comma inside). Option D is wrong because the regex pattern, while attempting to match commas outside quotes, is fragile and fails on edge cases like escaped quotes, uneven quote counts, or empty quoted fields; it also has poor performance on large files.

9
MCQeasy

Which of the following is the BEST practice for building a large string by concatenating many smaller strings in Python?

A.result = ''.join(parts)
B.result = sum(parts, '')
C.result = str.concat(*parts)
D.result = ''; for part in parts: result += part
AnswerA

''.join(parts) is the canonical and most efficient way to combine a sequence of strings in Python. It allocates exactly one new string object, iterates over parts once, and copies each part's characters into a pre-sized buffer, achieving O(n) time and minimal memory overhead. This method clearly communicates intent and avoids the quadratic behavior of repeated concatenation.

Why this answer

`''.join(parts)` is the most efficient way to concatenate a large number of strings in Python. It allocates memory once for the final string by iterating over the list and copying each part into the result buffer, avoiding the O(n²) time complexity of repeated concatenation in a loop.

Exam trap

Python Institute often tests the misconception that `+=` is acceptable for all string building, or that `sum` or non-existent methods like `str.concat` are valid, when in fact `''.join()` is the only efficient and correct approach for large concatenations.

How to eliminate wrong answers

Option B is wrong because `sum(parts, '')` is not intended for string concatenation; it performs addition with a start value of an empty string, which raises a TypeError because `sum` expects numeric types by default and does not support string concatenation. Option C is wrong because `str.concat(*parts)` is not a valid Python built-in method; there is no `str.concat` function, and this would raise an AttributeError. Option D is wrong because using `result += part` in a loop creates a new string object for each iteration, leading to O(n²) time complexity due to repeated memory allocation and copying, making it inefficient for large numbers of parts.

10
MCQmedium

Refer to the exhibit. Which of the following fixes the error?

A.print('Hello' + '5')
B.print('Hello' + str(5))
C.Both A and B
D.print('Hello' * 5)
AnswerC

Both A and B produce the intended output without error. Option A uses direct string concatenation with a string literal, while option B uses explicit conversion of the integer to a string. Neither causes a TypeError, so both fix the error described in the exhibit.

Why this answer

Both A and B produce the string 'Hello5' without error. In Python, the + operator concatenates strings, so 'Hello' + '5' works. Option B converts the integer 5 to a string using str() before concatenation, which also works.

Option D uses the * operator to repeat the string 'Hello' five times, producing 'HelloHelloHelloHelloHello', which is a valid operation but does not fix the error described in the exhibit (likely a TypeError from trying to concatenate a string and an integer).

Exam trap

Python Institute often tests the distinction between implicit type conversion (which Python does not do for string+int) and explicit conversion using str(), and candidates may forget that string repetition with * is valid but does not solve a concatenation error.

How to eliminate wrong answers

Option A is wrong because it is actually correct—it concatenates two strings without error, so it does fix the error. Option B is wrong because it is also correct—it converts the integer to a string before concatenation, fixing the error. Option D is wrong because while it is a valid Python expression, it repeats the string 'Hello' five times rather than concatenating it with 5, so it does not address the specific error of concatenating a string and an integer.

11
MCQmedium

A data analyst is cleaning a CSV file. They have a string variable containing a row of data: 'John,Doe,30,New York'. They need to extract the last name 'Doe' using string methods. The analyst writes: name = row.split(',')[1]. However, they are concerned about performance because the file contains millions of rows. They want to use a more efficient method that extracts the substring without creating a full list. Which approach should the analyst use?

A.Use split(',', 2) and take the second element
B.Use partition(',') and get the third element
C.Use rsplit(',', 1) and take the first part
D.Use string slicing after finding the comma positions: start = row.find(',')+1; end = row.find(',', start); name = row[start:end]
AnswerD

This technique directly extracts the substring between the first and second commas using index arithmetic. `row.find(',')` returns the index of the first comma, so adding 1 gives the character position immediately after it; then `row.find(',', start)` scans forward from that position to locate the second comma. Slicing `row[start:end]` copies only the needed characters and avoids creating a list of all fields, making it both memory-efficient and precise for this fixed-position CSV pattern.

Why this answer

It avoids creating a full list of all fields by using `find()` to locate the comma positions and then slicing the substring directly. This approach is more memory-efficient for millions of rows, as it only extracts the required portion without splitting the entire string into a list.

Exam trap

A common trap in PCAP is thinking that any split() variant is always the best approach, ignoring the memory overhead of list creation in performance-critical scenarios.

How to eliminate wrong answers

Option A is wrong because `split(',', 2)` still creates a list of up to 3 elements, which is more efficient than a full split but still allocates a list object for each row. Option B is wrong because `partition(',')` returns a tuple of three strings (before, separator, after), but the third element is the remainder after the first comma, not the last name; to get 'Doe', you would need the second element (the part between the first and second commas), which is not directly provided. Option C is wrong because `rsplit(',', 1)` splits from the right, returning a list of two elements where the first part is everything before the last comma, which would be 'John,Doe,30' — not the last name.

12
MCQmedium

A developer writes code to display a floating-point number with exactly two decimal places. Which f-string expression is correct for value = 3.14159?

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

This is the correct f-string format specifier: the dot ('.') introduces a precision field, '2' is the number of digits to display after the decimal point, and 'f' selects fixed-point notation. For example, f"{3.14159:.2f}" evaluates to '3.14', and Python automatically rounds the value to the requested precision. This matches the requirement to display exactly two decimal places, making it the only valid option among the choices.

Why this answer

The format specifier `.2f` in an f-string explicitly instructs Python to format the floating-point number with exactly two digits after the decimal point. The `f` type ensures fixed-point notation, and the precision `.2` controls the number of decimal places. This is the standard way to achieve two-decimal-place output for a float in Python.

Exam trap

Python exams often test the distinction between width and precision in format specifiers, trapping candidates who confuse `0.2` (width.precision without type) with `.2f` (precision with float type), or who mistakenly use `%` syntax from older Python formatting styles.

How to eliminate wrong answers

Option A is wrong because `0.2` is a width-and-precision specifier without a type code; it pads the number to a total width of 2 characters (including the decimal point) but does not guarantee two decimal places, and for `3.14159` it would produce `3.14159` (no truncation) or cause unexpected behavior. Option C is wrong because `%2f` is not a valid format specifier; the `%` character is used for old-style `%` formatting, not f-string syntax, and `2f` is misinterpreted. Option D is wrong because `2f` lacks a decimal point before the precision; it sets a minimum field width of 2 but does not specify decimal places, so it would output the full float without truncation (e.g., `3.14159`).

13
MCQeasy

A function receives a file path like '/home/user/docs/file.txt' and needs to return the path without the file extension, e.g., '/home/user/docs/file'. Which code reliably removes only the last dot extension, even if the directory names contain dots?

A.path.split('.')[0]
B.path.rsplit('.', 1)[0]
C.path.replace('.', '', 1)
D.path[:path.find('.')]
AnswerB

path.rsplit('.', 1) splits from the right side using a maxsplit of 1, so it stops after encountering the last dot in the string, and [0] gives the substring before that final dot. This correctly removes only the extension from a path such as '/home/user/file.txt', producing '/home/user/file' while preserving any dots in the directory path, as with '/home/user.name/file.txt' -> '/home/user.name/file'. It is the string-method idiom for stripping a trailing extension, although os.path.splitext is the more robust alternative in practice.

Why this answer

`rsplit('.', 1)` splits the string from the right, limiting the split to exactly one occurrence, which isolates the file extension (the part after the last dot) and returns everything before it. This reliably removes only the last dot extension, even if directory names contain dots, because it targets the final dot in the path.

Exam trap

The Python PCAP exam often tests the distinction between `split` and `rsplit` with the maxsplit parameter, and the trap here is that candidates mistakenly use `split('.')[0]` or `path[:path.find('.')]`, which fail when directory names contain dots because they target the first dot instead of the last.

How to eliminate wrong answers

Option A is wrong because `split('.')` splits on every dot in the path, returning a list of all segments; taking index `[0]` only gives the part before the first dot, which would incorrectly truncate the path at the first dot (e.g., '/home/user/docs' from '/home/user/docs/file.txt' becomes '/home/user/docs' instead of '/home/user/docs/file'). Option C is wrong because `replace('.', '', 1)` replaces only the first occurrence of a dot, which would remove the dot in a directory name (e.g., 'docs' in '/home/user/docs/file.txt' becomes '/home/user/docsfile.txt') rather than the extension dot. Option D is wrong because `path[:path.find('.')]` finds the index of the first dot and slices up to it, which again truncates at the first dot and fails if directory names contain dots (e.g., '/home/user/docs/file.txt' becomes '/home/user/docs').

14
MCQhard

You are developing a high-performance logging module that must handle thousands of log entries per second. Each entry is built by concatenating a timestamp, level, and message. Currently, your code uses a loop that repeatedly appends to a string using the += operator. This results in high memory usage and sluggish performance because each concatenation creates a new string object. The module must run on systems with limited memory and cannot rely on external libraries. Which course of action would best resolve the performance issue while maintaining readability and standard library compliance?

A.Collect the string parts in a list and use str.join() to combine them at the end.
B.Use string formatting (f-strings or format) within the loop to build the log entry.
C.Write the log entries directly to a file using file.write() in the loop.
D.Continue using += but preallocate a large string buffer using array.array or io.StringIO to reduce reallocation.
AnswerA

Accumulating fragments in a list and calling str.join() only at the end is efficient because Python can first calculate the total length of the combined result, allocate a single string buffer exactly once, and then copy each fragment into place. This avoids the O(n²) copying behavior of repeated concatenation, where each += operation allocates a new string and copies all previous content. For logging modules that assemble many small parts per entry, this is the recommended Pythonic pattern.

Why this answer

Collecting string parts in a list and using str.join() avoids repeated string concatenation, which creates a new string object for each += operation. This approach reduces memory allocation overhead and improves performance, especially under high throughput, while remaining fully compliant with standard library constraints.

Exam trap

Python Institute often tests the misconception that string formatting (f-strings) or incremental I/O (file.write) avoids the immutability penalty, when in fact they still create new string objects or introduce I/O latency, respectively.

How to eliminate wrong answers

Option B is wrong because using f-strings or format() inside the loop still creates a new string object per iteration, incurring the same memory and performance penalty as +=. Option C is wrong because writing directly to a file in the loop introduces I/O overhead for each log entry, which is slower than batching writes and may cause excessive disk writes under high load. Option D is wrong because preallocating a buffer with array.array or io.StringIO does not eliminate the fundamental issue of repeated string concatenation; io.StringIO is designed for incremental building but still involves internal reallocation, and array.array is not intended for string concatenation, leading to complexity and potential type errors.

15
MCQmedium

Refer to the exhibit. What is printed?

A.' Alice is 025 years old.'
B.' Alice is 25 years old.'
C.'Alice is 25 years old.'
D.' Alice is 25 years old.'
AnswerA

Correct: name right-aligned, age zero-padded.

Why this answer

The Python code uses an f-string with the format specifier `:>10s}` for the name and `:03d}` for the age. The `>10s` right-aligns the string 'Alice' in a field of width 10, producing 5 leading spaces. The `03d` formats the integer 25 as a zero-padded three-digit string '025'.

The final output is `' Alice is 025 years old.'`.

Exam trap

Python Institute often tests the subtle distinction between string padding (spaces) and numeric zero-padding, and the fact that the `>` alignment specifier applies to strings while `0` padding applies only to numbers, causing candidates to overlook the leading spaces or the zero-padded age.

How to eliminate wrong answers

Option B is wrong because it omits the leading spaces (the `>10s` specifier right-aligns the name in a 10-character field, producing 5 spaces before 'Alice') and incorrectly shows the age as '25' instead of zero-padded '025'. Option C is wrong because it incorrectly places spaces after 'Alice' (the `>10s` specifier right-aligns, not left-aligns, so spaces appear before, not after). Option D is wrong because it shows the age as '25' without the leading zero required by the `03d` format specifier.

16
MCQhard

A Python script reads a file containing text with non-ASCII characters like 'é' and 'ü'. The script must encode the string as UTF-8 then decode it back. Which of the following correctly handles this without error?

A.s.decode('utf-8').encode('utf-8')
B.s.encode('ascii').decode('ascii')
C.s.encode('utf-8').decode('utf-8')
D.s.decode('utf-8').decode('utf-8')
AnswerC

This is the correct round-trip: s.encode('utf-8') serializes the Unicode string into a bytes object using UTF-8's variable-length encoding, and .decode('utf-8') deserializes those exact bytes back into the original str. Because UTF-8 can encode every Unicode code point, the transformation is lossless and the resulting string is equal to s. Unlike the wrong options, it respects the proper direction (str → bytes → str) and never applies decode to a str. This pattern is commonly used when passing text through byte-oriented APIs or verifying byte-level round-trippability.

Why this answer

It first encodes the string (which contains non-ASCII characters like 'é' and 'ü') into UTF-8 bytes using `.encode('utf-8')`, then decodes those bytes back into a string using `.decode('utf-8')`. This round-trip preserves all characters since UTF-8 can represent any Unicode code point, and the operations are applied in the correct order: a string is encoded to bytes, then bytes are decoded back to a string.

Exam trap

Python Institute often tests the distinction between string and bytes methods — the trap here is that candidates confuse `.encode()` and `.decode()`, thinking both can be called on strings, or they incorrectly assume ASCII can handle non-ASCII characters without error.

How to eliminate wrong answers

Option A is wrong because it attempts to decode a string (which is already a Unicode object) using `.decode('utf-8')`, which raises an `AttributeError` — decode is a method of bytes, not str. Option B is wrong because it encodes the string to ASCII, which will raise a `UnicodeEncodeError` for non-ASCII characters like 'é' and 'ü' since ASCII only supports code points 0–127. Option D is wrong because it calls `.decode()` twice on a string, which is invalid for the same reason as Option A — the first decode fails, and even if it were bytes, double decoding would produce garbage or an error.

17
MCQhard

A team is using f-strings to format a report. They have a variable `value = 0.123456789` and want to display it with exactly 3 significant digits. They write `f"{value:.3g}"`. The output is '0.123'. They expected '0.123'. Is the output correct? If not, what change would produce '0.123'?

A.Use `f"{value:.3s}"`
B.Use `f"{value:.3f}"`
C.Use `f"{value:.3e}"`
D.The output is correct as is.
AnswerD

Correct—the format spec already in use (`.3g`) rounds to three significant digits and picks fixed-point notation for this magnitude. For `0.123456`, the three significant digits are 1, 2, and 3, and because the adjusted exponent is within the `g` threshold, it prints as `0.123` without an exponent. The output is exactly what the report requires, so no alternative specifier is needed.

Why this answer

The format specifier `.3g` in an f-string instructs Python to format the number with 3 significant digits using general format. For `0.123456789`, the first three significant digits are '123', and the general format automatically switches to fixed-point notation when the exponent is small, producing '0.123' exactly as expected.

Exam trap

The trap here is that candidates confuse 'significant digits' (controlled by `g`) with 'decimal places' (controlled by `f`), leading them to incorrectly choose `.3f` when `.3g` is the correct specifier for significant digits.

How to eliminate wrong answers

Option A is wrong because `s` is not a valid format type for numeric values; it is used for strings and would raise a ValueError. Option B is wrong because `.3f` formats with exactly 3 digits after the decimal point, which would produce '0.123' only by coincidence for this value, but it is not the correct approach for significant digits; for a value like 0.0012345, `.3f` would give '0.001' (only 1 significant digit), not 3. Option C is wrong because `.3e` forces scientific notation with 3 digits after the decimal point, producing '1.235e-01' (rounded), not '0.123'.

18
MCQmedium

A network engineer processes a configuration file containing MAC addresses in the format 'aa:bb:cc:dd:ee:ff'. They need to convert each MAC address into a 6-byte bytes object for use in packet crafting. The current code is: mac_bytes = bytes([int(x, 16) for x in mac_str.split(':')]). This works correctly, but they need to process thousands of MAC addresses and want to optimize performance. They also need to handle invalid MAC addresses (e.g., non-hex characters) without crashing. Which of the following approaches is the most efficient and robust?

A.Use the same list comprehension but add a try-except block for ValueError
B.Use bytes.fromhex(mac_str.replace(':', ''))
C.Use struct.pack('BBBBBB', *[int(x,16) for x in mac_str.split(':')])
D.Use a for loop to parse each pair and build a bytearray
AnswerB

bytes.fromhex() is a built-in method implemented in C that parses a hex string directly into a bytes object, making it the fastest and most idiomatic choice. Removing the colons with .replace(':', '') yields a 12-character hex string, which fromhex converts to exactly six bytes. It also performs validation in the C layer: non-hex characters or odd-length strings raise ValueError, giving the same error behavior as a manual parse but without Python-level iteration.

Why this answer

`bytes.fromhex()` is implemented in C, making it significantly faster than a Python-level list comprehension for thousands of conversions. It also inherently validates that the input contains only hexadecimal characters (and colons, which are ignored after removal), raising a `ValueError` for invalid input, which can be caught for robustness. This approach avoids the overhead of splitting, iterating, and calling `int()` for each octet.

Exam trap

The PCAP exam often tests the misconception that a list comprehension or `struct.pack` is the most efficient approach, when in reality Python's built-in `bytes.fromhex()` leverages C-level optimization for both speed and validation.

How to eliminate wrong answers

Option A is wrong because while it adds error handling, it still uses the slower list comprehension with `int(x, 16)` for each octet, which involves Python-level iteration and function calls, making it less efficient than the C-level `bytes.fromhex()`. Option C is wrong because `struct.pack()` adds unnecessary overhead by requiring the list comprehension to produce the integers first, then packing them into bytes; it is neither the most efficient nor the most direct method. Option D is wrong because a manual for loop with `bytearray` is the slowest approach, as it involves Python-level iteration, multiple function calls, and incremental appending, which is far less efficient than the single C-level call in Option B.

19
MCQmedium

A developer generates a report where numbers must be right-aligned in a 10-character column using f-strings: f'{value:>10}'. However, some values may be None, causing a TypeError. Which is the most robust way to handle None values without affecting other falsy values like 0?

A.Use str.format() with a conditional for the format spec
B.f'{value or "N/A":>10}'
C.f'{value if value is not None else "N/A":>10}'
D.Wrap the f-string in a try-except block
AnswerC

This option uses a conditional expression that explicitly tests identity with `is not None`, meaning only `None` triggers the fallback while preserving all other values, including 0 and empty strings. The f-string then applies the `:>10` format spec to the selected result, right-aligning either 'N/A' or the numeric value in a 10-character field. It is the only choice that correctly distinguishes a missing sentinel from legitimate falsy data.

Why this answer

It uses an explicit identity check (`value is not None`) to distinguish `None` from other falsy values like `0` or empty strings. This ensures that `0` is still right-aligned as a number, while `None` is replaced with the string `"N/A"` before formatting. The f-string then applies the `>10` alignment specifier to the resulting value.

Exam trap

The PCAP exam often tests the distinction between identity checks (`is None`) and truthiness checks (`or`, `if value`) to catch candidates who assume all falsy values should be treated equally, especially when `0` is a valid numeric value that must be preserved.

How to eliminate wrong answers

Option A is wrong because `str.format()` with a conditional for the format spec does not inherently handle `None` values; it would still raise a `TypeError` when trying to format `None` unless the conditional also replaces the value itself. Option B is wrong because `value or "N/A"` treats `0` (a falsy number) as `None`, incorrectly replacing it with `"N/A"` instead of preserving it for right-alignment. Option D is wrong because wrapping the f-string in a `try-except` block is a reactive approach that catches the `TypeError` at runtime, but it is less robust and less readable than a proactive conditional check; it also requires additional logic to decide what to display on exception.

20
MCQhard

What is the result of 'abcdef'[::-2]?

A.'dfb'
B.'ace'
C.'fdb'
D.'eca'
AnswerC

'fdb' is the correct result of the slice 'abcdef'[::-2]. The negative step tells Python to traverse the sequence backward from the last character, selecting 'f' (index 5), then 'd' (index 3), then 'b' (index 1). This is the only option that matches the requested backward, every-other-character behavior.

Why this answer

The slicing syntax [::-2] means start from the end (default step negative), go to the beginning, and take every second character in reverse order. For 'abcdef', starting at 'f' (index -1), then skipping one to 'd' (index -3), then 'b' (index -5), resulting in 'fdb'. Option C is correct.

Exam trap

Candidates often mistakenly think that [::-2] starts from the beginning and skips every two characters forward, leading them to pick 'ace' (option B) instead of understanding that a negative step reverses the traversal order.

How to eliminate wrong answers

Option A is wrong because 'dfb' would require a step of -2 starting from index -2 ('e'), which is not what [::-2] does. Option B is wrong because 'ace' is the result of a positive step of 2 from the beginning (i.e., 'abcdef'[::2]), not a negative step. Option D is wrong because 'eca' would be the result of reversing the string and then taking every second character from the start (i.e., 'fedcba'[::2]), which is a different operation.

21
MCQeasy

A developer wants to convert a string 'Python' to all uppercase letters. Which string method should be used?

A.capitalize()
B.title()
C.swapcase()
D.upper()
AnswerD

The `str.upper()` method returns a new string with all alphabetic characters converted to uppercase, leaving non-alphabetic characters unchanged. For the string `'Python'`, it produces `'PYTHON'` without modifying the original string, satisfying the requirement for a non-destructive transformation. This method operates on each Unicode character’s case mapping, ensuring correct conversion for the given ASCII input.

Why this answer

The `upper()` method returns a copy of the string with all lowercase characters converted to uppercase. Since the goal is to convert 'Python' to 'PYTHON', `upper()` is the correct and most direct method for this task.

Exam trap

The Python PCAP exam often tests the distinction between `upper()` and `capitalize()` or `title()`, where candidates mistakenly choose `capitalize()` thinking it converts the entire string to uppercase, but it only capitalizes the first character.

How to eliminate wrong answers

Option A is wrong because `capitalize()` converts only the first character to uppercase and the rest to lowercase, resulting in 'Python' (no change) or 'python' if the string were all lowercase. Option B is wrong because `title()` capitalizes the first character of each word, which for a single word like 'Python' would produce 'Python' (no change) and is not designed for full uppercase conversion. Option C is wrong because `swapcase()` inverts the case of each character, turning 'Python' into 'pYTHON', not the desired all-uppercase result.

22
MCQhard

A cloud infrastructure engineer is developing a Python script to parse large configuration files from a fleet of servers. Each file can be up to 500 MB. The script reads the file line by line using a file object, strips comment lines (those starting with '#'), and accumulates only the configuration directives into a single string for further processing. The current code is: ```python result = '' with open('config.cfg') as f: for line in f: if not line.startswith('#'): result += line.strip() ``` After processing just a few hundred lines of a large file, the script becomes extremely slow and consumes an excessive amount of memory. The engineer identifies that string concatenation using `+=` is inefficient because strings are immutable, causing repeated memory reallocation. Which approach should the engineer implement to resolve the performance issue without changing the final output?

A.Replace `result += line.strip()` with `result = result + line.strip()`.
B.Use `io.StringIO` to write lines and then retrieve content with `.getvalue()`.
C.Use `str.join` called on the file object: `f.join('')`.
D.Use a list to collect stripped lines and then call `''.join(lines)` after the loop.
AnswerD

Store each stripped line as an element in a list during the loop; appending to a list is amortized O(1). After the loop, call `''.join(lines)` to allocate the final string exactly once and copy each part in a single pass, producing O(n) total work. This is the canonical idiom because it avoids repeated string reallocation and takes advantage of `str.join`'s optimized internal traversal of the sequence.

Why this answer

It avoids the O(n²) time complexity of repeated string concatenation by collecting stripped lines in a list and then joining them once with `''.join(lines)`. This leverages the efficient memory allocation of `str.join`, which precomputes the total size and allocates exactly once, solving the performance and memory issue without altering the final output.

Exam trap

Candidates often incorrectly believe that `result = result + line.strip()` is more efficient than `result += line.strip()`, but both have the same O(n^2) performance due to string immutability. The correct solution is to collect lines in a list and join them with `''.join()`.

How to eliminate wrong answers

Option A is wrong because `result = result + line.strip()` is semantically identical to `result += line.strip()` — both create a new string object and cause the same O(n²) reallocation overhead. Option B is wrong because `io.StringIO` is designed for in-memory text streams and would still require a final `.getvalue()` call, but it does not inherently solve the concatenation inefficiency; it adds unnecessary overhead for this simple accumulation task. Option C is wrong because `str.join` is a method on a string separator, not on a file object; `f.join('')` would raise an `AttributeError` since file objects have no `join` method.

23
Matchingmedium

Match each exception to its cause.

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

Concepts
Matches

Operation on incompatible type

Function receives argument with correct type but invalid value

Sequence subscript out of range

Mapping key not found

Attribute reference or assignment fails

Why these pairings

Correct matches: ValueError with inappropriate value, TypeError with wrong type, IndexError with out-of-range index, KeyError with missing key. Common confusions arise from swapping the definitions of ValueError and TypeError, or TypeError and KeyError.

24
MCQmedium

A developer needs to parse a log file where each line contains a timestamp followed by a message. The timestamp format is 'YYYY-MM-DD HH:MM:SS'. Which string method is most appropriate to split the timestamp from the message?

A.str.rsplit()
B.str.splitlines()
C.str.partition()
D.str.split()
AnswerD

str.split() with no arguments splits on any run of whitespace, trimming leading and trailing spaces, and returns a list of non-empty substrings. For a log line like '2025-04-10 14:22:31 INFO message here', the timestamp (which contains no spaces) becomes the first element while the rest of the line is broken into subsequent elements, cleanly isolating the timestamp. It is the most direct method because it handles variable amounts of whitespace without requiring a separator to be specified.

Why this answer

Str.split(), is the most appropriate because it splits a string on whitespace by default. Although the timestamp 'YYYY-MM-DD HH:MM:SS' contains a space, using split() without arguments returns a list of all space-separated elements. Since the timestamp is always the first two elements (date and time), the developer can join them with a space to get the full timestamp.

Alternatively, split() can be used with a specified separator and maxsplit to achieve the desired split. This flexibility makes str.split() the best choice among the given options.

Exam trap

Python Institute often tests the distinction between str.split() and str.partition(), where candidates mistakenly choose str.partition() because they think it splits on the first space, but fail to realize that the timestamp itself contains a space, causing an incorrect split.

How to eliminate wrong answers

Option A is wrong because str.rsplit() splits from the right side of the string, which would incorrectly separate the last word of the message rather than the first space after the timestamp. Option B is wrong because str.splitlines() splits on line boundaries (newline characters), not on whitespace within a single line, so it cannot separate the timestamp from the message on the same line. Option C is wrong because str.partition() splits on the first occurrence of a specific separator string, but the timestamp contains spaces (between date and time), so using a space as the separator would split the timestamp itself, not separate it from the message.

25
MCQmedium

A developer needs to combine a list of 10,000 strings into a single string. Which approach is most efficient in terms of memory and performance?

A.Use ''.join(string_list)
B.Use a loop with str += to concatenate each string
C.Use str.replace() to merge the strings
D.Use str.format() to build the string step by step
AnswerA

The str.join() method is optimized for this exact use case. It first iterates over string_list to calculate the total length, allocates a single backing buffer of exactly that size, and then copies each string into place without creating any intermediate objects. This results in O(n) time and minimal memory overhead, so it is the canonical and most efficient way to concatenate many strings.

Why this answer

The `''.join(string_list)` method is the most efficient because it pre-allocates memory for the final string by first calculating the total length of all strings in the list, then building the result in a single pass. This avoids the quadratic time complexity and repeated memory reallocations caused by string immutability in Python when using `+=` in a loop.

Exam trap

Python Institute often tests the misconception that `+=` is efficient for string concatenation because it works in other languages, but in Python, string immutability makes it a performance disaster for large lists.

How to eliminate wrong answers

Option B is wrong because using `str +=` in a loop creates a new string object for each concatenation, leading to O(n²) time complexity and excessive memory allocation due to Python's immutable strings. Option C is wrong because `str.replace()` is designed for substring replacement, not concatenation, and would require an initial string to operate on, making it unsuitable and inefficient for merging a list of strings. Option D is wrong because `str.format()` is intended for formatting placeholders, not for concatenating an arbitrary list of strings, and using it iteratively would still involve repeated string creation and poor performance.

26
MCQmedium

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

27
MCQeasy

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

28
MCQhard

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

29
MCQmedium

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

30
MCQmedium

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

31
MCQhard

Refer to the exhibit. What is the output?

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

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

Why this answer

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

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

Exam trap

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

How to eliminate wrong answers

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

32
Multi-Selectmedium

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

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

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

Why this answer

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

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

Exam trap

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

33
Multi-Selecthard

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

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

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

Why this answer

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

Exam trap

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

34
Multi-Selectmedium

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

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

lstrip() specifically removes leading whitespace.

Why this answer

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

Exam trap

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

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

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

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

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

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

40
MCQhard

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

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

This is the exact error raised.

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

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

42
MCQhard

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

43
MCQhard

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

44
MCQeasy

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

45
MCQhard

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

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

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

Why this answer

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

Exam trap

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

How to eliminate wrong answers

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

46
Multi-Selecthard

Which TWO of the following expressions yield the substring 'Py' from the string s = 'Python'?

Select 2 answers
A.s[0:-4]
B.s[0:2:2]
C.s[-6:-3]
D.s[0:2]
E.s[0:1]
AnswersA, D

Correct: from 0 to -4 (exclusive), which is indices 0 and 1.

Why this answer

S[0:-4] uses negative indexing to slice from index 0 up to (but not including) index -4, which corresponds to the character 'o' (the fifth character from the end). Since 'Python' has length 6, index -4 is the character at position 2 (0-based), so the slice returns characters at indices 0 and 1, which are 'P' and 'y', yielding 'Py'.

Exam trap

Python Institute often tests the interaction between negative indexing and step values, trapping candidates who forget that a step of 2 skips characters or that negative indices count from the end, leading them to select options that return only one character or an incorrect substring.

47
Multi-Selectmedium

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

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

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

Why this answer

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

Exam trap

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

48
MCQeasy

A developer wants to check if a string ends with a specific suffix. Which method should be used?

A.endswith()
B.index()
C.find()
D.startswith()
AnswerA

The `endswith()` method is the dedicated predicate for suffix testing: it returns `True` only when the final characters of the string exactly match the given suffix, and `False` otherwise. It also accepts optional `start`/`end` slice arguments, which allow you to check only a portion of the string, and it performs a case-sensitive comparison by default (use `casefold()` or lowercasing for case-insensitive checks). Because it returns a boolean directly, it cleanly satisfies the developer's requirement to verify whether the string ends with a specific substring.

Why this answer

The `endswith()` method is specifically designed to check if a string ends with a given suffix, returning a boolean value. This is the correct and most direct approach for the task described, as it avoids manual slicing or comparison.

Exam trap

Python Institute often tests the distinction between `endswith()` and `startswith()`, trapping candidates who confuse prefix and suffix checks, or who mistakenly use `find()` or `index()` which locate substrings anywhere in the string rather than at the end.

How to eliminate wrong answers

Option B is wrong because `index()` returns the lowest index where a substring is found, or raises a ValueError if not found, and does not check for a suffix. Option C is wrong because `find()` returns the lowest index of the substring or -1 if not found, but does not test for the end of the string. Option D is wrong because `startswith()` checks if the string begins with a prefix, not a suffix.

49
MCQmedium

A developer tries to modify a string: s = 'hello'; s[0] = 'H'. What happens when this code runs?

A.It changes the string to 'Hello'
B.It raises a TypeError: 'str' object does not support item assignment
C.It creates a new string 'Hello' and assigns it to s
D.It raises an IndexError because index 0 is out of range
AnswerB

Strings in Python are immutable sequences; the assignment `s[0] = 'H'' attempts to mutate the object at index 0, which violates the immutable contract of the `str` type. The interpreter raises a `TypeError` specifically because `str` objects lack a `__setitem__` method, preventing item assignment. This directly satisfies the constraint that strings cannot be modified in-place in Python.

Why this answer

Strings in Python are immutable, meaning their contents cannot be changed after creation. Attempting to assign a new character to an index position (e.g., s[0] = 'H') raises a TypeError: 'str' object does not support item assignment. To modify a string, you must create a new string using slicing or concatenation.

Exam trap

The PCAP exam often tests the immutability of strings by presenting an assignment to an index, tricking candidates who confuse strings with mutable sequences like lists into thinking the string will be modified in place.

How to eliminate wrong answers

Option A is wrong because strings are immutable; assigning to an index does not modify the string in place, so it does not change to 'Hello'. Option C is wrong because Python does not automatically create a new string and reassign s; instead, it raises an error immediately. Option D is wrong because index 0 is valid for a non-empty string like 'hello'; the error is a TypeError, not an IndexError.

50
MCQeasy

A programmer writes a function that expects a string and returns it reversed. Which code snippet correctly reverses the string 'stressed' to 'desserts'?

A.result = s.reversed()
B.result = s[::-1]
C.s.reverse()
D.result = ''.join(reversed(s))
AnswerB, D

Using extended slice syntax with a step of `-1` creates a reversed copy of the entire string: `s[::-1]` means start at the end, go to the beginning, and step backward by one. This is the most idiomatic and concise way to reverse a string in Python, and it is often preferred for its readability and speed. Since strings are immutable, this operation allocates a new string object containing the characters in reverse order, leaving the original string unchanged.

Why this answer

Both option B and option D correctly reverse the string 'stressed' to 'desserts'. Option B uses slice notation `[::-1]`, which creates a reversed copy of the string by stepping from end to start with a step of -1. This is the most direct and idiomatic way to reverse a string in Python.

Option D uses `''.join(reversed(s))`: `reversed(s)` returns an iterator that yields characters in reverse order, and `join()` concatenates them into a new string. This is also a valid and correct approach. Option A is incorrect because strings do not have a `reversed()` method; `reversed()` is a built-in function.

Option C is incorrect because `.reverse()` is a list method, not a string method, and strings are immutable.

Exam trap

The Python Institute often tests whether candidates know that both slice notation `[::-1]` and the combination of `reversed()` with `join()` are valid ways to reverse a string. Candidates may incorrectly think only slicing is correct or overlook that `reversed()` returns an iterator that requires `join()` to produce a string.

How to eliminate wrong answers

Option A is wrong because `s.reversed()` is not a valid method; the correct built-in is `reversed(s)`, which returns a reverse iterator, not a string. Option C is wrong because `s.reverse()` is a list method, not a string method — strings are immutable and have no `.reverse()` method, so this raises an AttributeError. Option D is wrong because while `''.join(reversed(s))` does produce the reversed string, it is not listed as the correct answer in the given options; the question asks for the snippet that correctly reverses the string, and option B is the direct, idiomatic one-liner.

Ready to test yourself?

Try a timed practice session using only Strings questions.