Courseiva

CCNA Functions, Tuples, Dictionaries and Exceptions Questions

75 of 80 questions · Page 1/2 · Functions, Tuples, Dictionaries and Exceptions · Answers revealed

1
Multi-Selectmedium

Which THREE of the following statements about Python exception handling are correct?

Select 3 answers
A.The finally block always runs.
B.The else block runs if no exception occurred.
C.You must have at least one except block if you have a finally block.
D.You can have multiple except blocks for different exception types.
E.A try block must have at least one except block.
AnswersA, B, D

The finally clause executes regardless of whether an exception occurred or not.

Why this answer

The `finally` block in Python is guaranteed to execute regardless of whether an exception occurred, was caught, or even if the `try` block contains a `return`, `break`, or `continue` statement. This ensures cleanup actions like closing files or releasing resources always run.

Exam trap

The PCEP exam often tests the misconception that a `finally` block requires an accompanying `except` block, or that a `try` block must always have at least one `except` block, when in fact `try-finally` alone is valid Python syntax.

2
Multi-Selectmedium

Which TWO of the following are valid dictionary methods? (Select two.)

Select 2 answers
A.keys()
B.keyset()
C.entries()
D.pairs()
E.values()
AnswersA, E

keys() returns a view object of the dictionary's keys and is a genuine built-in dict method. It satisfies the question's requirement for a valid dictionary method, distinguishing it from list-only operations such as append or index.

Why this answer

The `keys()` method returns a view object displaying all keys in a dictionary, and `values()` returns a view object of all values. Both are built-in dictionary methods in Python, making them valid for the PCEP exam.

Exam trap

The exam often tests candidates by including method names from other languages (like Java's `keyset()` or `entries()`) to exploit confusion between Python and Java dictionary APIs.

3
MCQhard

An inventory script defines `def add_stock(item, quantity, *restock_dates):` and is called as `add_stock('bolt', 40, '2024-01-05', '2024-02-11')`. Inside the function, the developer wants to count how many restock dates were supplied. Which expression correctly reports that count?

A.len(restock_dates[0])
B.len(restock_dates)
C.restock_dates.length
D.restock_dates.count
AnswerB

A parameter prefixed with an asterisk collects any extra positional arguments into a tuple. Here restock_dates becomes ('2024-01-05', '2024-02-11'), so len(restock_dates) returns 2. Because it is a tuple, it supports len, indexing, and iteration, which is exactly how variadic functions inspect the surplus arguments they received.

Why this answer

The starred parameter packs all surplus positional arguments into a tuple, so the number of restock dates equals the length of that tuple. Calling the built-in len on the packed tuple gives the exact count of extra arguments received, while indexing or attribute-style length access either measures the wrong thing or fails outright.

Exam trap

The trap here is treating the packed parameter as if it had a length attribute or as if measuring one element summarized the whole collection, when only len on the tuple gives the total count.

4
MCQeasy

A developer writes a function to calculate the average of a list of numbers, but the function sometimes returns a wrong result when the list contains non-numeric values. What is the best way to handle this?

A.Return None if any non-numeric value is encountered.
B.Use try-except to ignore non-numeric values and proceed with the remaining numbers.
C.Convert all values to string and concatenate them.
D.Check that all items are numeric before calculation, and raise TypeError otherwise.
AnswerD

Validating every element with a numeric type check before summing prevents silent wrong results from strings or None. Raising TypeError signals invalid input explicitly, satisfying the requirement to handle non-numeric values rather than returning an incorrect average.

Why this answer

It explicitly validates that all items are numeric before performing the calculation, raising a TypeError if any non-numeric value is found. This follows Python's principle of explicit error handling and ensures the function's contract is clear: it only works with numeric data. Returning None (A) or silently ignoring values (B) can lead to subtle bugs, while converting to strings (C) would produce a concatenated string, not an average.

Exam trap

Python Institute often tests the distinction between silently handling errors (e.g., returning None or ignoring bad data) and explicitly raising exceptions, where candidates may mistakenly choose a 'graceful' option like ignoring non-numeric values, not realizing that it can lead to incorrect results without any warning.

How to eliminate wrong answers

Option A is wrong because returning None when encountering non-numeric values silently changes the return type, which can cause downstream code to fail unexpectedly (e.g., when trying to use the result in further arithmetic). Option B is wrong because using try-except to ignore non-numeric values silently discards data, producing an average that may be misleadingly incorrect without any indication of the omission. Option C is wrong because converting all values to strings and concatenating them produces a string, not a numeric average, which is a fundamental type error and completely misses the purpose of the function.

5
MCQeasy

What is the output of the following code? def greet(name, greeting='Hello'): print(greeting, name) greet('Alice')

A.Hello
B.Hello Alice
C.SyntaxError
D.Alice
AnswerB

Default parameters apply when an argument is omitted at call time. Calling `greet('Alice')` supplies only `name`, so Python binds `greeting` to its default value `'Hello'`, printing `Hello Alice`. The single positional argument satisfies `name`, leaving the optional parameter untouched.

Why this answer

The function `greet` has a default parameter `greeting='Hello'`. When called with only one argument (`'Alice'`), the default value is used for `greeting`, so the output is `Hello Alice`. The `print` function outputs both arguments separated by a space.

Exam trap

Python Institute often tests whether candidates understand that default parameters are used when the corresponding argument is omitted, leading to the misconception that only the default value is printed or that a syntax error occurs.

How to eliminate wrong answers

Option A is wrong because it omits the name argument; the function prints both the greeting and the name, not just the greeting. Option C is wrong because the function definition is syntactically valid (default parameters are allowed in Python) and the call with one argument matches the required parameter. Option D is wrong because it only prints the name, ignoring the default greeting that is explicitly printed.

6
MCQmedium

What is the output of the following dictionary comprehension? {x: x**2 for x in range(3)}

A.{0:0, 1:1, 2:4}
B.{0:1, 1:2, 2:3}
C.{0:0, 1:2, 2:4}
D.{1:1, 2:4}
AnswerA

The comprehension iterates x over range(3), giving 0, 1 and 2, and maps each to its square. The resulting dictionary pairs 0 with 0, 1 with 1 and 2 with 4, producing exactly {0:0, 1:1, 2:4}.

Why this answer

The dictionary comprehension `{x: x**2 for x in range(3)}` iterates over `x` values 0, 1, and 2 (from `range(3)`). For each `x`, it creates a key-value pair where the key is `x` and the value is `x**2` (x squared). This produces `{0: 0**2, 1: 1**2, 2: 2**2}`, which evaluates to `{0:0, 1:1, 2:4}`.

Exam trap

Python Institute often tests whether candidates remember that `range(3)` starts at 0, not 1, and that `0**2` equals 0, not an omitted or undefined value, causing many to drop the first key-value pair or miscalculate the square of 1.

How to eliminate wrong answers

Option B is wrong because it incorrectly maps each `x` to `x+1` (0→1, 1→2, 2→3), which is not what `x**2` computes. Option C is wrong because it shows `1:2` instead of `1:1`, likely confusing `x**2` with `x*2` (multiplication) or miscomputing `1**2` as 2. Option D is wrong because it omits the key `0` entirely, which would only happen if the comprehension started from `range(1,3)` or if the candidate mistakenly thought `0**2` is undefined or should be skipped.

7
Multi-Selectmedium

Which THREE of the following are valid dictionary methods? (Choose three.)

Select 3 answers
A..values()
B..append()
C..push()
D..keys()
E..get()
AnswersA, D, E

values returns a view of dictionary values.

Why this answer

The `.values()` method returns a view object that displays a list of all the values in a dictionary. It is a built-in dictionary method in Python, making option A correct.

Exam trap

The PCEP exam often tests the distinction between list methods (like `.append()`) and dictionary methods, trapping candidates who confuse data structure operations across types.

8
MCQmedium

A developer writes a function to update a configuration dictionary: def update_config(config, key, value): config[key] = value; return config. They call it as: my_config = {'debug': False}; result = update_config(my_config, 'debug', True). What is the value of my_config after the call, and why?

A.my_config remains {'debug': False} because integers and booleans are immutable and passed by value.
B.A TypeError is raised because dictionaries cannot be modified inside a function.
C.my_config becomes {'debug': True} only if the function returns the dictionary and the caller reassigns it.
D.my_config becomes {'debug': True} because the dictionary is passed by reference and modified in place.
AnswerD

Dictionaries in Python are mutable objects. When passed to a function, the parameter config refers to the same dictionary object as my_config. The statement config[key] = value mutates that shared object, so the caller sees the change. No copy is made unless explicitly requested. Thus my_config now maps 'debug' to True, and result also refers to the same updated dictionary.

Why this answer

Because dictionaries are mutable and passed into functions by object reference, assigning to a key inside the function updates the caller's dictionary. The original object is modified in place, so the change is visible outside the function without any return or reassignment. This behavior is central to Python's argument-passing semantics for mutable types.

Exam trap

The trap here is assuming that because the value True is immutable, the dictionary cannot change, when mutability of the container is what matters.

9
MCQmedium

A developer is writing a function that accepts a dictionary of student names and their scores. The function should return the name of the student with the highest score. If the dictionary is empty, it should return `None`. Which code snippet correctly implements this?

A.def top_student(scores): if len(scores) == 0: return None return max(scores.items())
B.def top_student(scores): return max(scores.values())
C.def top_student(scores): return max(scores)
D.def top_student(scores): if not scores: return None return max(scores, key=scores.get)
AnswerD

This function checks if the dictionary is empty and returns None. Otherwise, it uses max with the key argument set to scores.get, which retrieves the value for each key and returns the key with the highest value. This correctly identifies the top student.

Why this answer

To find the key with the maximum value in a dictionary, pass a key function to max that extracts the value for each key. Using `scores.get` as the key function achieves this. The empty check prevents a ValueError.

The other options either return the wrong element or fail on an empty dictionary.

Exam trap

The trap here is forgetting that iterating over a dictionary yields keys, so max without a key function compares keys, not values.

10
MCQhard

A function is defined as: def func(*args, **kwargs): print(args, kwargs). It is called as func(1, 2, a=3, b=4). What is printed?

A.(1, 2, a=3, b=4)
B.(1, 2) {'a': 3, 'b': 4}
C.TypeError
D.[1, 2] {'a': 3, 'b': 4}
AnswerB

Positional arguments 1 and 2 are collected into the args tuple, while keyword arguments a=3 and b=4 are collected into the kwargs dictionary. Printing both objects therefore yields the tuple (1, 2) followed by the dictionary {'a': 3, 'b': 4}.

Why this answer

The function uses `*args` to capture positional arguments into a tuple and `**kwargs` to capture keyword arguments into a dictionary. When called as `func(1, 2, a=3, b=4)`, `args` becomes `(1, 2)` and `kwargs` becomes `{'a': 3, 'b': 4}`, so `print(args, kwargs)` outputs `(1, 2) {'a': 3, 'b': 4}`. Option B is correct because it matches this exact output.

Exam trap

Python Institute often tests the distinction between `*args` (tuple) and `**kwargs` (dictionary), and the trap here is that candidates mistakenly think keyword arguments are included in the tuple or that `*args` produces a list, leading them to pick options A or D.

How to eliminate wrong answers

Option A is wrong because it incorrectly combines positional and keyword arguments into a single tuple, ignoring that `**kwargs` collects keyword arguments into a dictionary, not a tuple. Option C is wrong because no TypeError occurs; the function definition correctly accepts both `*args` and `**kwargs`, and the call provides valid positional and keyword arguments. Option D is wrong because `*args` always produces a tuple, not a list; Python's `*args` packs arguments into an immutable tuple, not a mutable list.

11
Multi-Selectmedium

Which TWO of the following are true about function arguments in Python? (Choose two.)

Select 2 answers
A.Arguments can be passed by position or keyword.
B.Default arguments are evaluated each time the function is called.
C.*args collects keyword arguments.
D.**kwargs collects positional arguments.
E.Default arguments are evaluated at function definition time.
AnswersA, E

Correct: Python supports both positional and keyword arguments.

Why this answer

Python allows function arguments to be passed either by position (matching the order of parameters in the function definition) or by keyword (using the parameter name explicitly). This flexibility is a core feature of Python's function call semantics, enabling clearer and more flexible code.

Exam trap

The PCEP exam often tests the distinction between *args (positional) and **kwargs (keyword) and the timing of default argument evaluation, hoping candidates confuse the asterisk syntax or assume defaults are re-evaluated on each call.

12
MCQhard

A critical automation system uses a try-except block to handle errors during file operations. The current code uses a bare except: clause to catch any error and perform cleanup. However, when an operator tries to stop the program with Ctrl+C, the KeyboardInterrupt exception is caught, and the cleanup routine runs, preventing a clean exit. Additionally, if the system runs out of memory, MemoryError is caught. The developers need to modify the exception handling so that system-exiting exceptions (such as KeyboardInterrupt and SystemExit) are not caught, but other exceptions (e.g., FileNotFoundError, PermissionError) are still handled for cleanup. Which modification best achieves this?

A.Change the bare except: to except Exception:
B.Remove the except block entirely and rely on a finally block for cleanup
C.Replace the single except block with multiple specific except blocks for each expected file error
D.Define a custom exception class and raise it for all file errors
AnswerA

except Exception: catches only subclasses of Exception, so FileNotFoundError and PermissionError still trigger cleanup, while KeyboardInterrupt and SystemExit (which derive from BaseException, not Exception) propagate and allow a clean exit. This precisely satisfies the requirement to exclude system-exiting exceptions.

Why this answer

Changing the bare `except:` to `except Exception:` ensures that only exceptions inheriting from the built-in `Exception` class are caught. System-exiting exceptions like `KeyboardInterrupt` and `SystemExit` inherit from `BaseException` directly, not from `Exception`, so they will propagate uncaught, allowing a clean exit. This preserves the cleanup behavior for file-related errors such as `FileNotFoundError` and `PermissionError`, which are subclasses of `Exception`.

Exam trap

The PCEP exam often tests the misconception that a bare `except:` is equivalent to `except Exception:`, when in fact it catches all `BaseException` subclasses, including `KeyboardInterrupt` and `SystemExit`, which should typically be allowed to terminate the program.

How to eliminate wrong answers

Option B is wrong because removing the `except` block entirely and relying solely on a `finally` block would not handle any exceptions at all; the program would crash on file errors without performing the intended cleanup. Option C is wrong because while multiple specific `except` blocks for file errors would work, they do not address the requirement to avoid catching system-exiting exceptions; a bare `except:` would still be needed for unexpected errors, which would again catch `KeyboardInterrupt`. Option D is wrong because defining a custom exception class and raising it for all file errors does not change which exceptions are caught by the existing bare `except:` clause; the bare `except:` would still catch `KeyboardInterrupt` and `SystemExit`.

13
MCQhard

A developer is writing a robust script that must handle file reading errors. The script should catch only I/O-related exceptions (e.g., FileNotFoundError, PermissionError) and let other exceptions propagate. Which exception handling structure is best suited?

A.Use a single bare except: clause
B.Use except: and then re-raise the exception
C.Use multiple except blocks for specific exception types
D.Use except Exception: as the only handler
AnswerC

Catching FileNotFoundError and PermissionError in separate except blocks lets the script handle each I/O failure precisely while unhandled exceptions, such as ValueError, propagate naturally. This satisfies the stem's requirement to catch only I/O-related exceptions, since a single broad handler would incorrectly intercept unrelated errors.

Why this answer

Using multiple `except` blocks for specific exception types (e.g., `FileNotFoundError`, `PermissionError`) allows the script to catch only I/O-related exceptions while letting all other exceptions propagate unhandled. This matches the requirement precisely, as each `except` clause targets a distinct exception class, and any unlisted exception will not be caught, preserving the intended error propagation behavior.

Exam trap

The PCEP exam often tests the misconception that a single `except Exception:` is sufficient for selective handling, but candidates fail to realize it catches all `Exception` subclasses, including non-I/O ones, thus violating the requirement to let other exceptions propagate.

How to eliminate wrong answers

Option A is wrong because a single bare `except:` clause catches all exceptions, including non-I/O ones like `KeyboardInterrupt` or `SystemExit`, which violates the requirement to let other exceptions propagate. Option B is wrong because using `except:` and then re-raising the exception still catches all exceptions initially, which is unnecessary and can mask the intent; it also does not selectively handle only I/O exceptions. Option D is wrong because `except Exception:` catches all subclasses of `Exception`, which includes many non-I/O exceptions (e.g., `ValueError`, `TypeError`), failing to let those propagate as required.

14
MCQhard

A function receives a dictionary that may contain nested dictionaries. The function must modify the dictionary without affecting the original passed argument. Which technique ensures a complete independent copy?

A.Use copy.deepcopy() from the copy module
B.Assign the dictionary to a new variable (e.g., new_dict = original)
C.Use copy.copy() on the original dictionary
D.Use dict.copy() method
AnswerA

copy.deepcopy() recursively duplicates every nested dictionary and list, producing a fully independent object graph. A shallow copy or dict() only copies the top level, leaving nested references shared, so mutations would still propagate to the original argument.

Why this answer

`copy.deepcopy()` recursively copies all objects within the dictionary, including nested dictionaries, creating a completely independent copy. This ensures modifications to the copy do not affect the original argument, which is required when the dictionary contains mutable nested structures.

Exam trap

The PCEP exam often tests the distinction between shallow and deep copies, and the trap here is that candidates assume `dict.copy()` or `copy.copy()` create a full independent copy, overlooking that nested dictionaries remain shared references.

How to eliminate wrong answers

Option B is wrong because assigning the dictionary to a new variable (e.g., `new_dict = original`) only creates a new reference to the same dictionary object, not a copy; any modification to `new_dict` directly mutates the original. Option C is wrong because `copy.copy()` performs a shallow copy, which duplicates the top-level dictionary but shares references to nested dictionaries, so changes to nested structures still affect the original. Option D is wrong because `dict.copy()` also performs a shallow copy, identical to `copy.copy()`, and does not handle nested dictionaries independently.

15
MCQeasy

A developer writes a function to calculate the area of a rectangle: def area(length, width): return length * width. They call it as area(5, 3). What is the result and why?

A.15, but only if the arguments are passed as area(length=5, width=3).
B.15, because the arguments are passed positionally, so length=5 and width=3.
C.A TypeError occurs because the function requires keyword arguments.
D.8, because the function adds the arguments instead of multiplying them.
AnswerB

When a function is called with positional arguments, they are matched to parameters in the order they are defined. Here, the first argument 5 binds to length and the second argument 3 binds to width. The multiplication 5 * 3 yields 15. No keyword arguments are used, so there is no ambiguity. This is the standard positional argument passing mechanism in Python.

Why this answer

Positional arguments are matched to parameters based on their order in the function call. The first argument binds to the first parameter, the second to the second, and so on. Since length and width are multiplied, area(5, 3) returns 15.

No keyword arguments are necessary, and the function does not enforce keyword-only parameters.

Exam trap

The trap here is thinking that keyword arguments are mandatory or that multiplication requires a specific argument order.

16
MCQhard

What is the output of the following code? def div(a, b): try: return a / b except ZeroDivisionError: raise ValueError('Invalid division') try: print(div(10, 0)) except ValueError as e: print(e) except ZeroDivisionError: print('Zero division')

A.Error: division by zero
B.Zero division
C.TypeError
D.Invalid division
AnswerD

The inner `except ZeroDivisionError` catches the division by zero and raises a new `ValueError('Invalid division')`. The outer `try` block's `except ValueError as e` handler catches this propagated exception and prints its message, so the output is `Invalid division`.

Why this answer

The `div` function catches the `ZeroDivisionError` and raises a `ValueError` with the message 'Invalid division'. The outer `try` block catches this `ValueError` and prints its message, which is 'Invalid division'.

Exam trap

The PCEP exam often tests the distinction between catching an exception and raising a different exception inside the handler, tricking candidates into thinking the original exception type (ZeroDivisionError) will still be caught by the outer handler.

How to eliminate wrong answers

Option A is wrong because the code does not print an 'Error: division by zero' message; the `ZeroDivisionError` is caught inside `div` and replaced with a `ValueError`. Option B is wrong because the outer `except ZeroDivisionError` clause is never triggered; the raised exception is a `ValueError`, not a `ZeroDivisionError`. Option C is wrong because no `TypeError` occurs; the division operation is valid in terms of types (both are integers), and the exception handling is correctly structured.

17
MCQhard

Which of the following will raise a TypeError?

A.t = (1, 2); t[0] = 3
B.lst = [1, 2]; lst.extend([3, 4])
C.x = {1, 2} & {2, 3}
D.d = {'a': 1}; d['b'] = 2
AnswerA

Assigning to an index of a tuple raises TypeError because tuples are immutable: their elements cannot be reassigned after creation. The statement `t[0] = 3` attempts item assignment on a tuple, which Python rejects outright, satisfying the stem's requirement for a TypeError rather than a silent success or a different exception.

Why this answer

Tuples are immutable in Python; attempting to assign a value to an element using indexing (e.g., `t[0] = 3`) raises a `TypeError` with the message 'tuple' object does not support item assignment. This is a fundamental property of the tuple data type, designed to create fixed sequences that cannot be changed after creation.

Exam trap

Python Institute often tests the distinction between mutable and immutable types, specifically that tuples cannot be modified after creation, while lists, sets, and dictionaries can be changed via their respective methods or assignments.

How to eliminate wrong answers

Option B is wrong because `lst.extend([3, 4])` is a valid list method that appends all elements from the iterable `[3, 4]` to the end of the list, modifying it in place without error. Option C is wrong because `x = {1, 2} & {2, 3}` performs a set intersection operation, which is perfectly valid and returns a new set `{2}`; no TypeError occurs. Option D is wrong because `d['b'] = 2` assigns a new key-value pair to the dictionary, which is a standard and allowed operation on mutable dictionaries.

18
MCQhard

A developer defines a function `def add_item(item, basket=[]):` and calls it multiple times without providing a basket argument. After three calls with different items, what is the content of the default basket?

A.Each call gets a fresh empty list, so the basket remains empty after each call.
B.A TypeError is raised because mutable default arguments are not allowed in Python.
C.The basket contains only the item from the most recent call, as previous items are overwritten.
D.The basket contains all three items from the three calls, because the default list is shared and mutated.
AnswerD

This is correct because the default argument `basket=[]` is evaluated once when the function is defined, creating a single list object. Each call that omits the basket argument uses that same list and appends the item, so all three items accumulate. This is a classic Python pitfall with mutable default arguments.

Why this answer

Default arguments are evaluated once at function definition, so a mutable default like a list is shared across all calls that do not provide an explicit argument. The list is modified in place with each append, causing all items to accumulate. The other options incorrectly assume per-call initialization, overwriting, or a runtime error.

Exam trap

The trap here is assuming that default arguments are re-evaluated on each call, leading to the belief that the basket would be empty or contain only the latest item.

19
MCQeasy

What happens when you try to modify a tuple? t = (1, 2, 3) t[0] = 0

A.A TypeError is raised
B.A IndexError is raised
C.The tuple becomes (0, 2, 3)
D.The code runs without error
AnswerA

Tuples are immutable, so item assignment such as t[0] = 0 is unsupported. Python raises a TypeError at runtime rather than silently ignoring the change, which is the defined behaviour for attempting to modify tuple elements.

Why this answer

Tuples are immutable, so trying to assign to an index raises a TypeError.

20
MCQmedium

A developer writes a function to safely divide two numbers and wants to explicitly raise a ValueError when the divisor is zero, rather than letting a ZeroDivisionError propagate. The function signature is `def safe_divide(a, b):`. Which code snippet correctly accomplishes this?

A.if b = 0: raise ValueError('Cannot divide by zero') then return a / b
B.try: return a / b except ZeroDivisionError: raise ValueError
C.if b == 0: raise ValueError('Cannot divide by zero') then return a / b
D.assert b != 0, 'Cannot divide by zero' then return a / b
AnswerC

This is correct because it checks the divisor before performing division and explicitly raises ValueError with a custom message when b is zero. This prevents a ZeroDivisionError from occurring and gives the caller a more meaningful exception. The return statement executes only when b is non-zero, ensuring safe division.

Why this answer

The correct approach checks the divisor explicitly and raises a ValueError with a clear message before any division occurs. This prevents the built-in ZeroDivisionError and gives the caller a domain-specific exception. The other options either use the wrong exception type, rely on assertions that can be disabled, or contain syntax errors that prevent execution.

Exam trap

The trap here is confusing assert with raise, or assuming that catching ZeroDivisionError and re-raising ValueError is equivalent to explicitly raising before division.

21
Multi-Selectmedium

A developer is working with a dictionary `config = {'host': 'localhost', 'port': 8080}`. They need to perform operations that modify or access the dictionary without causing errors. Which two of the following operations are valid and will not raise an exception? (Choose two.)

Select 2 answers
A.`config.remove('host')`
B.`config['timeout']`
C.`config.pop('timeout')`
D.`config.get('timeout')`
E.`config['port'] = 9090`
AnswersD, E

The `get` method returns None if the key is not found, without raising an exception. It is a safe way to access a key that may not exist. In this case, 'timeout' is not present, so it returns None. This operation is valid and will not raise an error.

Why this answer

The `get` method safely retrieves a value without raising an exception if the key is missing, returning None. Assigning to an existing key simply updates the value. Both are valid operations that do not cause errors, unlike bracket access for missing keys, `pop` without default, or using a non-existent method.

Exam trap

The trap here is confusing dictionary methods with list methods or assuming that bracket access is safe for missing keys, leading to incorrect selections.

22
MCQmedium

A logistics team stores shipment data as `shipment = {'id': 'A17', 'weight_kg': 12.5, 'destination': 'Osaka'}`. A developer needs to retrieve the destination but wants the program to keep running and supply the string 'UNKNOWN' if the key is ever missing from a shipment record. Which statement should the developer use?

A.shipment['destination'] or 'UNKNOWN'
B.shipment.get('destination', 'UNKNOWN')
C.shipment.pop('destination', 'UNKNOWN')
D.shipment.setdefault('destination', 'UNKNOWN')
AnswerB

The dict.get method returns the value mapped to the key when the key exists, and it returns the second argument as a default when the key is absent, so missing keys never raise an error. In this scenario it yields 'Osaka' for the current record and 'UNKNOWN' for any record lacking a destination, letting the program continue processing shipments.

Why this answer

Reading a dictionary value without risking a KeyError requires a method that accepts a default, and dict.get is the standard tool for that. It returns the stored value when the key is present and the supplied fallback when it is not, without altering the dictionary. Methods that insert or remove keys change the record's contents, which the scenario does not permit.

Exam trap

The trap here is assuming that subscript access combined with a logical fallback is equivalent to a default-returning lookup, when in fact the missing key raises KeyError before any fallback logic runs.

23
MCQeasy

Given a list of names = ['Alice', 'Bob', 'Charlie'], a developer wants to create a dictionary mapping each name to its length. Which expression accomplishes this?

A.{len(name): name for name in names}
B.{name: len(name) for name in names}
C.{name: len for name in names}
D.{name: length for name in names}
AnswerB

The dictionary comprehension iterates over each element in `names`, binding `name` to the string and computing `len(name)` as its value, producing `{'Alice': 5, 'Bob': 3, 'Charlie': 7}`. This satisfies the requirement to map every name to its length in a single expression, unlike `map` or `zip` alternatives.

Why this answer

It uses a dictionary comprehension that iterates over each name in the list, using the name as the key and the result of `len(name)` as the value. This directly maps each name to its length, which is exactly what the developer wants.

Exam trap

The trap here is that candidates may confuse the key-value order in a dictionary comprehension or forget to call `len()` as a function, leading them to pick options that either swap the mapping or use an undefined variable.

How to eliminate wrong answers

Option A is wrong because it uses `len(name)` as the key and `name` as the value, which would create a dictionary mapping lengths to names (e.g., {5: 'Alice', 3: 'Bob', 7: 'Charlie'}), not names to lengths. Option C is wrong because `len` is a function object, not a function call; it would store the function itself as the value for each name, not the length of the name. Option D is wrong because `length` is an undefined variable; it would raise a NameError at runtime, as there is no variable named `length` in scope.

24
MCQmedium

A developer writes a function that attempts to access a dictionary key that may not exist: def get_value(data, key): try: return data[key] except KeyError: return None. They call it as get_value({'a': 1}, 'b'). What is the result and why?

A.The function returns 1 because it falls back to the first available key.
B.The function returns the string 'KeyError' because the exception is converted to a string.
C.None is returned because the KeyError is caught and handled.
D.A KeyError is raised because the key 'b' is not in the dictionary.
AnswerC

When data[key] is evaluated and the key 'b' is not found, a KeyError is raised. The except KeyError block catches this specific exception and executes its body, which returns None. The function then exits normally. This demonstrates how exception handling can provide a fallback value instead of crashing. The caller receives None as the result.

Why this answer

The function uses a try-except block to handle a potential KeyError. When the key 'b' is not found, the exception is caught, and the except block returns None. This provides a safe way to access dictionary values without causing the program to crash.

The caller receives None as the result of the function call.

Exam trap

The trap here is forgetting that the except block handles the exception, so no error is raised to the caller.

25
MCQmedium

A function is defined as: def min_max(nums): return min(nums), max(nums). What type of value does it return?

A.A tuple
B.A set
C.A dictionary
D.A list
AnswerA

Returning comma-separated values from a function packs them into a single tuple, so `min_max` yields a two-element tuple containing the minimum and maximum. This satisfies the stem's requirement to identify the return type: the parentheses are optional, but the comma operator always constructs a tuple.

Why this answer

The function `min_max` uses `return min(nums), max(nums)`, which is a comma-separated list of expressions. In Python, when multiple values are returned separated by commas, they are automatically packed into a tuple. Therefore, the function returns a tuple containing the minimum and maximum values.

Exam trap

The PCEP exam often tests the misconception that multiple return values are returned as a list or that parentheses are required to create a tuple, but in Python, it is the comma that defines a tuple, not the parentheses.

How to eliminate wrong answers

Option B is wrong because a set is created with curly braces or the `set()` constructor, and returning values separated by commas does not produce a set. Option C is wrong because a dictionary requires key-value pairs, but the function returns two values without any keys. Option D is wrong because a list is created with square brackets, and the comma syntax in a return statement does not produce a list.

26
MCQeasy

A Python developer is writing a function that takes a tuple of numbers and returns a new tuple containing only the even numbers. They write the following code: def filter_even(numbers): result = () for num in numbers: if num % 2 == 0: result += (num,) return result What is the primary reason this function works correctly?

A.Tuples support the append method, which adds elements to the end of the tuple in place.
B.Tuples are immutable, but the += operator creates a new tuple each time, which is then reassigned to result.
C.The += operator modifies the tuple in place by adding the new element to the existing tuple object.
D.The function returns a list, not a tuple, because += converts the tuple to a list.
AnswerB

The `+=` operator on a tuple does not modify the original tuple in place because tuples are immutable. Instead, it creates a new tuple by concatenating the existing tuple with the new element, then rebinds the variable `result` to this new tuple. This allows the function to accumulate even numbers correctly, as each iteration produces a new tuple.

Why this answer

The function correctly builds a tuple of even numbers because the `+=` operator, when used with tuples, creates a new tuple by concatenation and reassigns it to the variable. Tuples are immutable, so this is the only way to 'modify' them. The other options incorrectly describe tuple immutability or methods.

Exam trap

The trap here is thinking that tuples can be modified in place or that they have methods like `append`, but they are immutable and only support concatenation.

27
MCQeasy

A developer writes a function that assigns a new value to an element of a list passed as an argument. After the function returns, the caller observes that the original list has been modified. The developer wants a second function that appends an item to a list but leaves the caller's list unchanged. Which definition achieves this?

A.def add_item(lst, item): lst = lst + [item] return lst
B.def add_item(lst, item): lst += [item] return lst
C.def add_item(lst, item): lst.insert(0, item) return lst
D.def add_item(lst, item): lst.append(item) return lst
AnswerA

The expression lst + [item] creates a brand-new list object and rebinds the local name lst to it. The caller's original list object is never mutated, so after the function returns the caller still sees the unchanged list. The new list is returned for the caller to use if desired, which satisfies the requirement of appending without affecting the caller's list.

Why this answer

Passing a list to a function passes a reference to the same object, so any in-place method such as append, insert, or += alters the caller's data. Only creating a new list object, as with the concatenation lst + [item], avoids mutating the caller's list while still producing an appended result that can be returned.

Exam trap

The trap here is assuming that any assignment inside a function, including augmented assignment on a list parameter, creates a local copy and therefore protects the caller's object.

28
MCQeasy

Which of the following correctly creates a tuple with a single element 5?

A.t = (5,)
B.t = (5)
C.t = (5)
D.t = (5, 5)
AnswerA

Correct. The trailing comma is required to create a single-element tuple.

Why this answer

In Python, a tuple with a single element requires a trailing comma after the element. Without the comma, parentheses are treated as grouping operators for expression evaluation, not as a tuple literal. Thus, `t = (5,)` creates a tuple containing the integer 5.

Exam trap

The trap here is that candidates mistakenly believe parentheses alone create a tuple, overlooking the mandatory trailing comma for single-element tuples, which Cisco tests to distinguish between tuple creation and simple expression grouping.

How to eliminate wrong answers

Option B is wrong because `t = (5)` does not create a tuple; the parentheses are interpreted as grouping, so `t` becomes the integer 5. Option C is identical to B and also wrong for the same reason. Option D is wrong because `t = (5, 5)` creates a tuple with two elements, not a single element.

29
MCQeasy

A developer writes a function that takes a tuple as an argument and tries to modify an element inside the tuple. What happens?

A.The code raises a TypeError.
B.The tuple is converted to a list automatically.
C.The first element is modified successfully.
D.The code raises a ValueError.
AnswerA

Tuples are immutable, so any assignment to an index raises a TypeError at runtime. The interpreter blocks the modification rather than silently ignoring it, which satisfies the stem's scenario of attempting to change a tuple element.

Why this answer

Tuples in Python are immutable, meaning their elements cannot be changed after creation. Attempting to modify an element (e.g., `my_tuple[0] = 5`) raises a `TypeError` because the tuple object does not support item assignment. This is a fundamental property of the tuple data type.

Exam trap

Python Institute often tests the distinction between `TypeError` and `ValueError` — the trap here is that candidates may confuse an operation that is not allowed (TypeError) with an operation that receives an invalid value (ValueError).

How to eliminate wrong answers

Option B is wrong because Python never automatically converts a tuple to a list when modification is attempted; such an operation simply raises an error. Option C is wrong because tuples are immutable, so no element can be modified successfully. Option D is wrong because a `ValueError` is raised for inappropriate values, not for operations that are not supported by the object type; the error here is a `TypeError`.

30
MCQhard

Which exception is raised when trying to access a dictionary key that does not exist?

A.KeyError
B.TypeError
C.ValueError
D.AttributeError
AnswerA

Accessing a missing dictionary key raises KeyError, satisfying the stem's requirement for the exception triggered by absent keys. Python's dict lookup invokes `__getitem__`, which raises KeyError rather than returning a default, unlike `get()`. This distinguishes it from IndexError, used by sequences such as lists and tuples.

Why this answer

In Python, when you attempt to access a dictionary key that does not exist using square bracket notation (e.g., `my_dict['nonexistent']`), the interpreter raises a `KeyError`. This is the standard exception for missing dictionary keys, as defined in the Python language specification. The correct answer is A.

Exam trap

Python Institute often tests whether candidates confuse `KeyError` with `ValueError` or `TypeError`, especially when the question involves dictionary operations like `pop()` or `del` on a missing key, where the same `KeyError` is raised.

How to eliminate wrong answers

Option B (TypeError) is wrong because `TypeError` occurs when an operation or function is applied to an object of inappropriate type (e.g., adding a string to an integer), not when a key is missing from a dictionary. Option C (ValueError) is wrong because `ValueError` is raised when a function receives an argument with the right type but an inappropriate value (e.g., `int('abc')`), not for missing dictionary keys. Option D (AttributeError) is wrong because `AttributeError` occurs when an invalid attribute reference or assignment is made (e.g., `None.some_method`), not when accessing a non-existent dictionary key.

31
MCQeasy

A developer writes a function `def log_event(message, level='INFO'):` that appends a formatted string to a list. The developer calls `log_event('disk full')` and then `log_event('retrying', level='WARN')`. What is the result of these two calls?

A.The first call uses 'INFO' for level and the second uses 'WARN', because the default applies only when the argument is omitted.
B.The first call raises a TypeError because a function with a default parameter must always receive that argument explicitly.
C.The second call raises a TypeError because positional and keyword arguments cannot be mixed in the same call.
D.Both calls use 'WARN', because the second call permanently changes the default for later invocations.
AnswerA

Default parameter values are used only when the caller does not supply that argument. The first call omits level, so the default 'INFO' is bound; the second call passes level explicitly by keyword, which overrides the default with 'WARN'. Both calls succeed and produce the intended log entries for the developer.

Why this answer

Default arguments make a parameter optional and are bound only when the caller omits that argument. An explicit keyword argument replaces the default for that single call without changing the function's definition, so the first invocation logs at INFO and the second at WARN. Calls that mix positional and keyword arguments are valid when each parameter is filled once.

Exam trap

The trap here is believing that passing a keyword argument in one call rewrites the function's default, when defaults are fixed at definition time and merely overridden per call.

32
Multi-Selecthard

Which of the following statements about function arguments are true? (Select all that apply)

Select 4 answers
A.Keyword arguments can be passed in any order, regardless of their position in the function definition.
B.Using **kwargs allows passing a variable number of keyword arguments.
C.The *args parameter must always come after **kwargs in a function definition.
D.Using *args in a function definition allows passing a variable number of positional arguments.
E.Default arguments are evaluated once when the function is defined, not each time it is called.
AnswersA, B, D, E

Keyword arguments bind by parameter name rather than position, so the caller may supply them in any sequence and Python still maps each value to the matching parameter. This satisfies the stem's requirement that ordering is irrelevant, unlike positional arguments, which must follow the definition's sequence exactly.

Why this answer

The correct statements are A, B, D, and E. Keyword arguments can be passed in any order because they are matched by name (A). The **kwargs parameter collects additional keyword arguments into a dictionary (B).

The *args parameter collects additional positional arguments into a tuple (D). Default arguments are evaluated once at function definition time (E). Option C is incorrect because *args must always appear before **kwargs in a function definition.

Exam trap

A common pitfall in the PCEP exam is the order of *args and **kwargs: *args must precede **kwargs. Also, candidates often incorrectly think default arguments are evaluated each call, but they are evaluated once at definition time.

33
MCQhard

A developer writes a function that retrieves a value from a dictionary and handles missing keys: def get_value(data, key): try: return data[key] except KeyError: return None What happens if data is not a dictionary but a list, and key is an integer index?

A.The function returns None because the except KeyError clause catches any error.
B.The function raises a KeyError because lists use integer indices, not keys.
C.The function raises a TypeError because lists do not support the [] operator.
D.The function returns the element at the specified index because lists support integer indexing.
AnswerD

Lists support integer indexing, so data[key] with an integer key retrieves the element at that position. The try block succeeds, and the function returns that element. The except KeyError clause is not triggered because no KeyError occurs. Thus, the function works correctly for lists with integer indices, returning the desired element.

Why this answer

The function uses a try-except block to handle KeyError, which is specific to dictionary key lookups. When data is a list and key is an integer, the expression data[key] performs list indexing, which succeeds if the index is valid. No KeyError is raised, so the except block is skipped, and the element is returned.

This shows that the same syntax can work for different types, but the exception handling is tailored to dictionaries.

Exam trap

The trap here is assuming that the except KeyError clause will catch any error or that list indexing raises KeyError.

34
MCQmedium

A developer needs to count how many times each word appears in a list named words. The code starts with counts = {} and then iterates over the list. Which loop body correctly increments the count for each word, creating the key when it is first seen?

A.counts[word] += 1
B.counts.setdefault(word) + 1
C.counts[word] = counts.get(word, 0) + 1
D.counts.update(word, counts[word] + 1)
AnswerC

The get method returns the current count if the key exists and 0 otherwise, so the expression always produces a valid integer to increment. Assigning the result back to counts[word] creates the key on first encounter and updates it thereafter. This one-line idiom avoids a KeyError and correctly accumulates frequencies for every distinct word in the list.

Why this answer

Counting occurrences requires reading a possibly missing key without raising an exception and then storing the incremented value. The get method supplies a fallback of 0 for absent keys, and assigning the sum back to the dictionary both creates and updates the entry. The other forms either raise KeyError on first sight of a word or misuse a dictionary method.

Exam trap

The trap here is assuming that counts[word] += 1 initialises a missing key to zero automatically, when in fact it raises KeyError on the first occurrence.

35
Multi-Selectmedium

Which TWO of the following statements about tuples in Python are true?

Select 2 answers
A.Tuples are always hashable.
B.Tuples can be used as dictionary keys if all elements are hashable.
C.Tuples do not support indexing.
D.Tuples can only contain immutable objects.
E.Tuples are immutable sequences.
AnswersB, E

Dictionary keys require hashability, and a tuple is hashable when every contained element is hashable. Immutability alone is insufficient; a tuple holding a list cannot serve as a key, so the condition on all elements is the precise constraint.

Why this answer

Option B is correct because a tuple is hashable only when every element it contains is hashable, so a tuple such as (1, 'a') can serve as a dictionary key, while one containing a list cannot. Option E is correct because tuples are immutable sequences: once created, their length and element references cannot be changed, though they support indexing, slicing, concatenation, and repetition. Option A is wrong because tuples containing mutable or unhashable elements, such as ([1, 2],), are not hashable.

Option C is wrong because tuples fully support indexing and slicing, e.g., t[0]. Option D is wrong because tuples may contain mutable objects like lists; the tuple itself is immutable, but its elements need not be.

Exam trap

Python Institute often tests the misconception that 'tuples are immutable' automatically means 'tuples are always hashable' or 'tuples can only contain immutable objects,' leading candidates to incorrectly select options A or D.

36
MCQmedium

A developer is writing a function that should accept any number of positional arguments and return their sum. Which function definition correctly achieves this?

A.def sum_all(*args): return sum(*args)
B.def sum_all(*args): return sum(args)
C.def sum_all(**args): return sum(args)
D.def sum_all(args): return sum(args)
AnswerB

The *args syntax collects all positional arguments into a tuple named args, which can then be passed to the built-in sum function. This allows the function to accept zero or more arguments. It is the standard way to define a variadic function in Python.

Why this answer

The *args parameter collects any number of positional arguments into a tuple, which can then be summed using the built-in sum function. The other options either accept only a single iterable, collect keyword arguments instead, or incorrectly unpack the tuple when calling sum, leading to errors.

Exam trap

The trap here is confusing *args with **args, or incorrectly unpacking the tuple when passing to sum, which would cause a TypeError.

37
MCQmedium

A developer wants to raise a ValueError with a custom message when a negative number is passed. Which code is correct?

A.raise ValueError "Negative input not allowed"
B.raise ValueError() + "Negative input not allowed"
C.raise ValueError("Negative input not allowed")
D.raise new ValueError("Negative input not allowed")
AnswerC

The raise statement instantiates ValueError with the custom message string passed as its argument, immediately propagating the exception. This satisfies the requirement to raise ValueError with a custom message when a negative number is supplied, using correct Python exception-raising syntax.

Why this answer

In Python, raising an exception with a custom message requires passing the message as an argument to the exception constructor: `raise ValueError("Negative input not allowed")`. This creates a ValueError instance with the specified message, which is the standard and only syntactically valid way to include a custom message in a raise statement.

Exam trap

The PCEP exam often tests the distinction between correct Python syntax for raising exceptions and common mistakes from other languages (like using `new` or omitting parentheses), so candidates must remember that Python uses `raise ExceptionClass("message")` without any extra keywords.

How to eliminate wrong answers

Option A is wrong because `raise ValueError "Negative input not allowed"` omits parentheses; Python requires parentheses to call the constructor, and without them it is a syntax error. Option B is wrong because `raise ValueError() + "Negative input not allowed"` attempts to concatenate a ValueError instance (which does not support the + operator with a string) with a string, causing a TypeError. Option D is wrong because `raise new ValueError(...)` uses the `new` keyword, which is not valid Python syntax — Python does not use `new` to instantiate objects.

38
MCQeasy

A developer wants to create a tuple containing a single integer value 5. Which code snippet correctly creates such a tuple?

A.t = [5]
B.t = (5)
C.t = 5
D.t = (5,)
AnswerD

The trailing comma is what makes this a tuple rather than an integer in parentheses. Python's grammar requires that comma to disambiguate a single-element tuple from a grouped expression, so `(5,)` satisfies the stem's constraint of holding exactly one integer, 5. Without it, `t = (5)` binds an int.

Why this answer

A tuple with a single element requires a trailing comma to disambiguate it from a parenthesized expression. Without the comma, Python treats parentheses as grouping operators, not tuple syntax. Thus, `(5,)` creates a tuple containing the integer 5, while `(5)` is just the integer 5.

Exam trap

The PCEP exam often tests the misconception that parentheses alone create a tuple, leading candidates to choose `(5)` instead of `(5,)`.

How to eliminate wrong answers

Option A is wrong because `[5]` creates a list, not a tuple. Option B is wrong because `(5)` is a parenthesized integer expression, not a tuple; Python evaluates it as the integer 5. Option C is wrong because `t = 5` assigns an integer to the variable, not a tuple.

39
Multi-Selecteasy

Which THREE of the following are built-in exceptions in Python? (Select three.)

Select 3 answers
A.StopIteration
B.ValueError
C.LoopError
D.TypeError
E.DivisionError
AnswersA, B, D

Correct.

Why this answer

StopIteration is a built-in exception in Python that is raised to signal the end of an iterator. It is automatically raised by the __next__() method when there are no further items to iterate over, and is caught by for loops internally to terminate iteration.

Exam trap

The PCEP exam often tests candidates by including plausible-sounding but non-existent exception names like 'LoopError' or 'DivisionError', expecting test-takers to rely on memory of actual built-in exceptions rather than guessing based on similarity to common error messages.

40
MCQeasy

A programmer needs to store a fixed set of error codes that should not change during program execution. Which data type is most appropriate for this purpose?

A.tuple
B.dictionary
C.set
D.list
AnswerA

A tuple is immutable, so once it is created, its elements cannot be changed. This makes it ideal for storing a fixed set of error codes that should not be modified during program execution. The programmer can be confident that the collection remains constant, preventing accidental changes. Tuples also support indexing and iteration, making them convenient for lookups.

Why this answer

A tuple is an immutable sequence, so its contents cannot be altered after creation. This ensures that the set of error codes remains constant throughout the program's execution. While lists, dictionaries, and sets can hold multiple values, they are all mutable, meaning they could be accidentally modified.

The immutability of tuples makes them the most appropriate choice for storing fixed data.

Exam trap

The trap here is confusing immutability with uniqueness or assuming that any collection type can serve as a constant.

41
MCQhard

A payroll script calls `calculate_bonus(employee_id, base)` inside a try block. The function raises a custom exception `BonusError` when the employee is not eligible, and the script wants to log that specific failure while still letting an unexpected ZeroDivisionError propagate to a global handler. Which except clause should the developer write?

A.except BonusError or ZeroDivisionError as err:
B.except BonusError, ZeroDivisionError as err:
C.except BonusError as err:
D.except Exception as err:
AnswerC

Catching the specific exception type handles only the anticipated ineligibility case and binds the exception instance to err for logging. Any other exception, such as ZeroDivisionError, does not match this clause and therefore propagates to the outer handler. This selective approach gives precise control over which failures are swallowed and which are escalated.

Why this answer

Naming a single specific exception type in an except clause handles exactly that failure and lets everything else propagate. Binding it with as captures the instance for logging without broadening the catch. Catching a base class or listing unrelated types would either swallow unexpected errors or fail syntactically, defeating the script's escalation requirement.

Exam trap

The trap here is believing that writing two exception class names separated by a comma or the word or catches both, when Python 3 requires a parenthesized tuple and evaluates or to a single class.

42
MCQmedium

A junior developer wrote a function that calculates the average of a list of numbers. Inside the function, they used a variable named 'list' to store the input parameter. Later, they tried to call the built-in list() function to convert a string to a list inside the same function, but it raised a TypeError. The error occurs because the name 'list' now refers to the parameter, not the built-in. The function must be fixed without changing its external behavior. Which solution is the best practice?

A.Use the global keyword to refer to the built-in list
B.Use the builtins module (import builtins; builtins.list()) to call the built-in
C.Rename the local variable to something else, like 'lst' or 'data'
D.Remove the local variable and use the input parameter directly
AnswerC

Rebinding the name 'list' shadows the built-in, causing the TypeError. Renaming the local variable removes the shadowing while preserving the function's signature and return value, so external behaviour is unchanged. This is the standard fix for name shadowing in Python.

Why this answer

The best practice is to avoid shadowing built-in names. By renaming the parameter from 'list' to something like 'lst' or 'data', the built-in list() function remains accessible, and the function's external behavior is unchanged. This approach is simple, readable, and follows Python's naming conventions.

Exam trap

The PCEP exam often tests the concept of name shadowing, where candidates mistakenly think that using the 'global' keyword or importing builtins is the proper fix, instead of simply renaming the local variable to avoid shadowing the built-in function.

How to eliminate wrong answers

Option A is wrong because using the 'global' keyword would refer to a global variable named 'list', not the built-in function, and it does not solve the name shadowing issue. Option B is wrong because while importing builtins and calling builtins.list() technically works, it is unnecessarily complex and not considered best practice when a simple rename solves the problem cleanly. Option D is wrong because removing the local variable and using the input parameter directly would change the function's internal logic and potentially break code that relies on the parameter being stored in a variable.

43
Drag & Dropmedium

Order the steps to create and use a list in Python.

Drag or tap steps into the slots.

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

Why this order

Lists are created with brackets, assigned to variables, accessed by index, modified by assignment, and grown with methods.

44
MCQhard

What is the output of the following code? def f(): try: raise ValueError('error1') except ValueError: raise TypeError('error2') try: f() except TypeError as e: print(e) except ValueError: print('ValueError')

A.error2
B.Error: unhandled exception
C.error1
D.ValueError
AnswerA

The inner except catches ValueError, then raises TypeError, which propagates uncaught by f(). The outer handler matching TypeError prints its message, so 'error2' is emitted; the ValueError clause never executes because no ValueError reaches the outer try.

Why this answer

The code raises a `ValueError` inside the `try` block of function `f()`, which is caught by the `except ValueError` handler. That handler then raises a new `TypeError('error2')`. This new exception propagates out of `f()` and is caught by the outer `except TypeError as e` block, which prints the exception message `'error2'`.

Exam trap

The PCEP exam often tests the misconception that the original exception's message or type will be printed, when in fact the `except` block raises a completely new exception that replaces the original.

How to eliminate wrong answers

Option B is wrong because the `TypeError` raised inside the `except ValueError` block is explicitly caught by the outer `except TypeError` handler, so no exception goes unhandled. Option C is wrong because `'error1'` is the message of the original `ValueError`, but that exception is caught and replaced by the `TypeError` before any output occurs. Option D is wrong because the outer `except ValueError` block is never executed — the exception that propagates from `f()` is a `TypeError`, not a `ValueError`.

45
MCQhard

Consider the code: try: try: raise TypeError except ValueError: print('A') except TypeError: print('B') finally: print('C'). What is printed?

A.A, B, and C
B.C only
C.B and C
D.A and C
AnswerC

The inner raise TypeError is not caught by the ValueError handler, so it propagates to the outer except TypeError, printing B. The finally block always executes, printing C afterwards. The ValueError branch never runs, so A is never printed.

Why this answer

The inner `try` raises a `TypeError`. The inner `except ValueError` does not catch it, so the exception propagates to the outer `except TypeError`, which catches it and prints 'B'. The `finally` block always executes, printing 'C'.

Thus, the output is 'B' and 'C'.

Exam trap

The PCEP exam often tests the distinction between exception types and the order of `except` blocks, tricking candidates into thinking a `finally` block suppresses exception propagation or that an inner `except` catches unrelated exception types.

How to eliminate wrong answers

Option A is wrong because it suggests 'A' is printed, but the `except ValueError` does not catch a `TypeError`, so 'A' is never printed. Option B is wrong because it claims only 'C' is printed, ignoring that the `TypeError` is caught by the outer `except TypeError`, which prints 'B'. Option D is wrong because it includes 'A', which is never printed, and omits 'B', which is printed.

46
MCQeasy

A function `def process(data):` modifies the dictionary passed as argument by adding a new key. The developer wants to avoid modifying the original dictionary. What should the function do?

A.Create a copy of the dictionary at the start: `data = data.copy()`
B.Add the key, then delete it at the end.
C.Modify directly; changes to mutable objects are local only.
D.Convert the dictionary to a tuple before processing.
AnswerA

Dictionaries are mutable and passed by object reference, so adding a key inside the function mutates the caller's original. Calling data.copy() creates a shallow copy bound to the local name, so subsequent key additions affect only the copy, leaving the caller's dictionary unchanged.

Why this answer

Dictionaries are mutable objects in Python, so passing a dictionary to a function passes a reference to the same object. Calling `data.copy()` creates a shallow copy of the dictionary, allowing the function to modify the copy without affecting the original dictionary. This is the standard Pythonic way to avoid side effects on mutable arguments.

Exam trap

Python Institute often tests the misconception that mutable objects are passed by value or that changes inside a function are local, leading candidates to incorrectly choose Option C, which is false for mutable types like dictionaries and lists.

How to eliminate wrong answers

Option B is wrong because adding a key and then deleting it at the end still modifies the original dictionary during execution, which defeats the purpose of avoiding modification; the original dictionary is changed temporarily and may cause issues if an exception occurs before deletion. Option C is wrong because changes to mutable objects like dictionaries are not local — they affect the original object outside the function, as Python passes references to mutable objects, not copies. Option D is wrong because converting a dictionary to a tuple is not possible (tuples are immutable sequences, not mappings) and would raise a TypeError; even if converted, the original dictionary remains unmodified, but the approach is invalid and does not solve the problem.

47
MCQmedium

A Python script uses a dictionary to store user session data. The developer writes `user = {'id': 101, 'name': 'Alice'}` and later tries to access `user['email']`. What is the outcome?

A.It returns an empty string.
B.It raises a KeyError.
C.It returns None.
D.It checks the 'in' operator automatically and returns False.
AnswerB

Accessing a missing key with subscript notation raises KeyError, because dictionaries do not return a default for absent keys. The stem's `user` dictionary holds only `'id'` and `'name'`, so `user['email']` fails immediately at runtime rather than returning `None`.

Why this answer

In Python, accessing a dictionary key that does not exist raises a KeyError. The dictionary `user` contains only the keys 'id' and 'name', so `user['email']` triggers a KeyError because the key 'email' is not present. This is a fundamental behavior of Python dictionaries, which do not return default values for missing keys unless a method like `.get()` is used.

Exam trap

Python Institute often tests the distinction between direct bracket access (which raises KeyError) and the `.get()` method (which returns None or a default), tempting candidates to think Python automatically returns a falsy value for missing keys.

How to eliminate wrong answers

Option A is wrong because Python dictionaries never return an empty string for a missing key; they raise a KeyError instead. Option C is wrong because `None` is only returned when using the `.get()` method with no default argument, not with direct bracket access. Option D is wrong because the `in` operator is not automatically invoked when accessing a key; it must be explicitly used to check membership, and even then it returns a boolean, not the value.

48
MCQhard

What is the output of the following code? def test(): try: return 1 finally: return 2 print(test())

A.None
B.Error
C.2
D.1
AnswerC

A `finally` block's `return` overrides any `return` in the `try` block, so the value 2 replaces the pending 1 before the function exits. Python discards the earlier return value once `finally` executes its own `return`, making 2 the printed output.

Why this answer

In Python, a `finally` block always executes, and if both `try` and `finally` contain `return` statements, the `return` in `finally` overrides the one in `try`. The function `test()` returns 2, not 1, because the `finally` block's return value is the one that is actually used.

Exam trap

The PCEP exam often tests the misconception that a `try` block's return will take precedence over a `finally` block's return, leading candidates to pick option D (1) instead of understanding that `finally` overrides the return value.

How to eliminate wrong answers

Option A is wrong because the function does return a value (2), not None. Option B is wrong because no error occurs; the `finally` block executes cleanly and returns a value. Option D is wrong because although `return 1` is executed in the `try` block, the `finally` block's `return 2` overrides it, so the function returns 2, not 1.

49
MCQmedium

A developer writes a function to log sensor readings. The function is defined as: def log_reading(sensor_id, value, unit="C"): return f"{sensor_id}: {value}{unit}" The developer calls log_reading("T1", 22, unit="F"). What is the result?

A.A SyntaxError because keyword arguments must come before positional arguments.
B.A TypeError because the function expects three arguments and only two positional arguments were given.
C."T1: 22C"
D."T1: 22F"
AnswerD

The function has a default parameter unit with default value "C", but the caller explicitly passes unit="F" as a keyword argument. This overrides the default, so the returned string uses "F" as the unit. The value 22 is passed positionally to the value parameter. Therefore, the f-string evaluates to "T1: 22F".

Why this answer

The function call provides two positional arguments ("T1" and 22) and one keyword argument (unit="F"). The keyword argument overrides the default value "C". The f-string then interpolates sensor_id, value, and unit, producing "T1: 22F".

This demonstrates how default parameters can be overridden by explicit keyword arguments in a function call.

Exam trap

The trap here is assuming that a default parameter value always takes precedence or that keyword arguments cannot override defaults.

50
Drag & Dropmedium

Order the steps to define a class and create an object in Python.

Drag or tap steps into the slots.

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

Why this order

In Python, to define a class and create an object, you must first write a class definition using the `class` keyword, which typically includes the `__init__` method (the constructor) to initialize attributes. After that, you instantiate the class by calling it like a function, optionally passing arguments to `__init__`. Finally, you use the resulting object by accessing its attributes or calling its methods.

Any deviation from this order, such as instantiating before defining the class or omitting the constructor, will lead to errors because the class must exist and be properly defined before any objects can be created.

51
MCQhard

In a try-except block, a developer has two except clauses: except ValueError: and except: (bare except). If the code in the try block raises a ValueError, which except clause is executed?

A.Both in order
B.Neither; program crashes
C.The ValueError except clause
D.The bare except clause
AnswerC

Python evaluates except clauses in written order, and a specific handler takes precedence over a bare except. Since ValueError matches the named clause first, that handler runs; the bare except only catches exceptions no earlier clause matched.

Why this answer

When a ValueError is raised in the try block, Python searches the except clauses in the order they appear. It finds the first matching clause, which is `except ValueError:`, and executes it. The bare `except:` clause is only reached if no preceding named except clause matches the exception type.

Exam trap

The PCEP exam often tests the order of except clauses and the fact that Python executes only the first matching handler, leading candidates to mistakenly think both clauses run or that the bare except overrides a specific match.

How to eliminate wrong answers

Option A is wrong because Python executes only the first matching except clause, not both; after handling the ValueError, control passes to the code after the try-except block. Option B is wrong because the ValueError is explicitly caught by the `except ValueError:` clause, so the program does not crash. Option D is wrong because the bare `except:` clause is a catch-all that only runs if no earlier except clause matches the exception; since ValueError matches the first clause, the bare except is skipped.

52
MCQhard

A developer writes a function that reads an integer from a string and adds it to a running total. The code uses try: total += int(value) followed by except ValueError: total += 0. During testing, a value of '12.5' is supplied. What is the resulting behaviour?

A.The program terminates with an unhandled ValueError because except clauses cannot add to variables defined outside the function.
B.The conversion succeeds and total is increased by 12 because int truncates the decimal portion.
C.A TypeError is raised because the except clause names ValueError rather than the broader Exception class.
D.The ValueError handler runs, total is incremented by 0, and execution continues normally.
AnswerD

int('12.5') raises ValueError because the string contains a decimal point that int cannot parse. The except ValueError clause matches that exception, so its body executes and adds zero to the running total. Because the exception is handled, the program does not terminate; control resumes after the try-except statement, which is the intended graceful-degradation behaviour.

Why this answer

int applied to the string '12.5' cannot produce an integer and raises ValueError. The except ValueError clause matches that exception type, so its body runs, adding zero to the total and allowing execution to continue. The conversion does not silently truncate string decimals, and the handler is correctly typed to catch exactly this failure.

Exam trap

The trap here is confusing int's behaviour on a float object, where it truncates, with its behaviour on a string such as '12.5', where it raises ValueError.

53
MCQmedium

A programmer needs to store configuration settings keyed by string, where each key maps to a list of allowed values. Which data structure is most appropriate?

A.A tuple of lists where each list starts with the key.
B.A dictionary where keys are strings and values are lists.
C.A list of tuples where each tuple contains a key and a list of values.
D.A set of strings representing the keys, with a separate list for values.
AnswerB

A dictionary maps each string key directly to its associated list, giving O(1) average lookup by key. This satisfies the stem's requirement for string-keyed configuration where each key holds multiple allowed values, since lists preserve the ordered collection of values per key without needing separate parallel structures.

Why this answer

A dictionary in Python provides direct key-to-value mapping, making it ideal for storing configuration settings where each string key must map to a list of allowed values. Dictionaries offer O(1) average-time complexity for lookups, which is efficient for retrieving the list of values for a given key. This structure directly models the requirement without unnecessary nesting or indirection.

Exam trap

Python Institute often tests the distinction between data structures that store pairs (like dictionaries) versus those that store sequences (like lists or tuples), and the trap here is that candidates may choose a list of tuples (Option C) because it visually pairs keys and values, but overlook that it lacks the efficient key-based lookup that a dictionary provides.

How to eliminate wrong answers

Option A is wrong because a tuple of lists where each list starts with the key is not a native Python data structure for keyed access; it would require linear scanning to find a key, which is inefficient and error-prone. Option C is wrong because a list of tuples, while able to store key-value pairs, does not provide direct key-based lookup and would require O(n) search time, defeating the purpose of a configuration store. Option D is wrong because using a set of strings for keys with a separate list for values fails to associate each key with its specific list of values, making it impossible to retrieve the correct list for a given key without additional logic.

54
MCQmedium

A developer wants to create a dictionary that maps employee IDs to their department names. The IDs are integers, and departments are strings. Which of the following correctly creates such a dictionary?

A.employees = {101: "HR", 102: "IT"}
B.employees = dict(101: "HR", 102: "IT")
C.employees = dict(101="HR", 102="IT")
D.employees = dict([101, "HR"], [102, "IT"])
AnswerA

This uses a dictionary literal with integer keys and string values. The syntax {key: value, ...} is the standard way to create a dictionary. It correctly maps employee IDs (101 and 102) to department names ("HR" and "IT"). This is valid and creates the desired dictionary.

Why this answer

The dictionary literal {101: "HR", 102: "IT"} is the correct syntax for creating a dictionary with integer keys and string values. The dict() constructor can also be used, but keyword arguments cannot have integer names, and passing multiple positional arguments is invalid. The literal syntax is straightforward and commonly used for this purpose.

Exam trap

The trap here is confusing dictionary literal syntax with the dict() constructor's keyword argument syntax, or misusing the dict() constructor with multiple arguments.

55
MCQmedium

A developer is writing a Python function that must accept any number of positional arguments and return their sum. The function should also work when called with zero arguments. Which function definition correctly achieves this?

A.def total(nums): return sum(nums)
B.def total(nums=0): return sum(nums)
C.def total(*nums): return sum(nums)
D.def total(*nums): return sum(*nums)
AnswerC

Using *nums in the parameter list collects all positional arguments into a tuple named nums, which works even when no arguments are passed (nums becomes an empty tuple). The built-in sum() then returns 0 for an empty tuple, satisfying the zero-argument requirement.

Why this answer

The function must handle any number of positional arguments, including zero. Using *nums in the function definition collects arguments into a tuple, and sum() correctly adds them, returning 0 for an empty tuple. Other options either restrict the number of arguments or incorrectly unpack the tuple.

Exam trap

The trap here is confusing the parameter syntax *nums (which collects arguments) with the call syntax sum(*nums) (which unpacks), leading to a TypeError when the tuple is empty or when elements are not iterable.

56
MCQhard

A developer is using a lambda function that takes two arguments and returns their sum. Which of the following lambda expressions is correct?

A.lambda a, b: a + b
B.lambda a, b: a - b
C.lambda a, b: return a + b
D.def add(a, b): return a + b
AnswerA

Python lambda syntax places parameters before the colon and the single return expression after it, with no return keyword. Writing lambda a, b: a + b correctly declares two parameters and returns their sum, matching the two-argument addition requirement exactly.

Why this answer

Option A correctly defines a lambda function that takes two arguments and returns their sum. Option B is a valid lambda but returns the difference (a - b), not the sum, so it does not meet the requirement. Option C is incorrect because lambda expressions cannot include a `return` statement; the result is implicitly returned.

Option D uses `def` to define a named function, not a lambda.

Exam trap

Python Institute often tests the misconception that lambda requires an explicit `return` statement, leading candidates to choose Option C, but in reality the expression after the colon is automatically returned.

How to eliminate wrong answers

Option B is wrong because it is syntactically identical to Option A, but the question asks for 'which of the following lambda expressions is correct' and only one answer is marked as correct; in this context, Option B is a duplicate and not the intended correct choice. Option C is wrong because it uses `return` inside a lambda, which is invalid syntax — lambda bodies can only contain a single expression, not a statement like `return`. Option D is wrong because it is a regular function definition using `def`, not a lambda expression, so it does not meet the requirement of being a lambda.

57
MCQhard

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

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

The loop rebinds the same variable each iteration, and the final assignment leaves it holding 2. Printing after the loop completes therefore emits 2 2 2, because all three print calls reference the variable's last value rather than capturing each iteration's value separately.

Why this answer

The code defines a tuple `t = (0, 1, 2)`. The `for` loop iterates over the tuple, but each iteration prints `t[2]`, which is the third element (index 2) with value 2. Since the value is constant, it prints '2' three times.

Hence the output is '2 2 2'.

Exam trap

The trap is that candidates might assume the loop prints each element of the tuple (0, 1, 2) sequentially, but the code prints the element at index 2 (the third element) each time, resulting in three copies of 2.

How to eliminate wrong answers

Option A is wrong because it assumes the loop prints the current element `x` (0, 1, 2) rather than the fixed index `t[0]`. Option B is wrong because it assumes `t[0]` changes during iteration or that the tuple is modified, but tuples are immutable and `t[0]` remains `2`. Option D is wrong because it assumes the loop runs three times and prints `t[0]` but mistakenly thinks `t[0]` is `3`, which is not an element of the tuple.

58
MCQhard

A function is defined to accept a variable number of positional arguments and return their sum. The code is: def total(*args): return sum(args) What is the result of `total(1, 2, 3)`?

A.A tuple `(1, 2, 3)`
B.6
C.A TypeError is raised.
D.0
AnswerB

The function uses *args to collect all positional arguments into a tuple. When called with 1, 2, 3, args becomes (1, 2, 3). The built-in sum function then adds these numbers, resulting in 6. This is the correct output.

Why this answer

The *args parameter collects the positional arguments into a tuple. The sum function then adds the elements of that tuple. With arguments 1, 2, and 3, the sum is 6.

Thus, the function returns 6.

Exam trap

The trap here is thinking that the function returns the tuple of arguments, but it actually returns the computed sum.

59
Multi-Selectmedium

Which TWO of the following are valid ways to create a dictionary with initial key-value pairs? (Select exactly 2)

Select 2 answers
A.d = {'a': 1, 'b': 2}
B.d = ('a'=1, 'b'=2)
C.d = dict.fromkeys(['a', 'b', 'c']) # without value
D.d = dict(a=1, b=2)
E.d = dict(['a', 'b'], [1, 2])
AnswersA, D

Standard dictionary literal.

Why this answer

It uses the standard literal syntax for creating a dictionary with initial key-value pairs. The curly braces `{}` with colon-separated keys and values are the most common and direct way to define a dictionary in Python.

Exam trap

Python Institute often tests the distinction between the literal `{}` syntax and the `dict()` constructor, and candidates may mistakenly think that `dict()` can accept two separate lists as positional arguments, similar to how `zip()` works, or that parentheses can be used to define a dictionary.

60
MCQmedium

A developer writes a function that appends an item to a list: def add_item(item, my_list=[]): my_list.append(item); return my_list. They call add_item(1) twice. What are the return values of the two calls?

A.[1] and [1]
B.[1] and [1,1]
C.TypeError
D.[1] and [2]
AnswerB

The default list argument is evaluated once at function definition, so the same mutable list object persists across calls. The first call appends 1, returning [1]; the second appends to that same list, returning [1, 1]. This is Python's classic mutable default argument pitfall.

Why this answer

The default argument `my_list=[]` is evaluated only once at function definition time, not each time the function is called. Therefore, the first call `add_item(1)` appends 1 to the same list object, returning `[1]`. The second call appends another 1 to that same list, returning `[1, 1]`.

This is a classic Python gotcha involving mutable default arguments.

Exam trap

The PCEP exam often tests the mutable default argument trap — the trap here is that candidates mistakenly believe default arguments are re-evaluated on every function call, leading them to choose option A, when in fact they are evaluated only once at definition time.

How to eliminate wrong answers

Option A is wrong because it assumes the default list is recreated on each call, which is not how Python handles mutable default arguments — the list persists across calls. Option C is wrong because no TypeError occurs; the function is called correctly with a single positional argument, and the default list handles the missing second argument. Option D is wrong because it suggests the second call returns `[2]`, which would require the item argument to be 2 or some other mutation, but the same integer 1 is appended both times.

61
MCQeasy

A developer wants to use a tuple to store the names of the months. They attempt to change an element: months = ("Jan","Feb","Mar"); months[1] = "Februar". What is the result?

A.The tuple is updated to ("Jan","Februar","Mar")
B.A ValueError is raised
C.An AttributeError is raised
D.A TypeError is raised
AnswerD

Tuples are immutable sequences, so item assignment is unsupported. Attempting `months[1] = "Februar"` invokes the tuple's missing `__setitem__` behaviour, raising `TypeError: 'tuple' object does not support item assignment`. This satisfies the stem's constraint that the element change cannot succeed, unlike a list, which permits such mutation.

Why this answer

Tuples in Python are immutable, meaning their elements cannot be changed after creation. Attempting to assign a new value to an index of a tuple (e.g., months[1] = "Februar") raises a TypeError, not a ValueError or AttributeError. This is because the assignment operation is not supported for tuple objects.

Exam trap

The PCEP exam often tests the distinction between mutable (list) and immutable (tuple) types, and the trap here is that candidates confuse the immutability error with a ValueError or AttributeError, or assume tuples can be modified like lists.

How to eliminate wrong answers

Option A is wrong because tuples are immutable, so the assignment fails and the tuple remains unchanged; it is not updated. Option B is wrong because a ValueError is raised for operations like unpacking with wrong number of values or invalid literal conversion, not for attempting to modify an immutable object. Option C is wrong because an AttributeError occurs when accessing a method or attribute that does not exist on an object (e.g., months.append()), not when performing an assignment to an index.

62
MCQhard

A developer is writing a function that retrieves a value from a nested dictionary based on a sequence of keys. If any key is missing, the function should raise a custom exception MissingKeyError with the missing key. The function signature is def get_nested(data, keys):. Which implementation correctly meets these requirements?

A.def get_nested(data, keys): for key in keys: if key not in data: raise MissingKeyError(key) data = data[key] return data
B.def get_nested(data, keys): for key in keys: data = data.get(key) if data is None: raise MissingKeyError(key) return data
C.def get_nested(data, keys): for key in keys: if key not in data: raise MissingKeyError data = data[key] return data
D.def get_nested(data, keys): try: for key in keys: data = data[key] return data except KeyError: raise MissingKeyError
AnswerA

This implementation iterates through the keys, checks if each key exists in the current dictionary, and raises MissingKeyError with the missing key if not. It then descends into the nested dictionary. This correctly handles missing keys at any level and returns the final value. It uses the 'in' operator to check membership, which is efficient for dictionaries.

Why this answer

The correct implementation must check each key's presence, raise MissingKeyError with the missing key, and traverse the nested structure. The chosen option does exactly that using the 'in' operator and passes the key to the exception. The others either omit the key in the exception, mishandle None values, or raise the exception class without arguments.

Exam trap

The trap here is using dict.get() and checking for None, which conflates missing keys with keys that have None values, or forgetting to pass the missing key to the custom exception.

63
MCQmedium

A developer defines a tuple `config = ('localhost', 8080, True)`. Later, the code attempts `config[1] = 9090`. What happens when this line executes?

A.The tuple is updated in place, and config becomes ('localhost', 9090, True).
B.The assignment succeeds only if the new value is of the same type as the old value.
C.A new tuple is created automatically with the updated value, and config is rebound to it.
D.A TypeError is raised because tuple objects do not support item assignment.
AnswerD

Tuples are immutable sequences. Any attempt to assign to an index, such as config[1] = 9090, raises TypeError with a message like 'tuple' object does not support item assignment. The tuple itself remains unchanged. This is the correct behavior for the given code.

Why this answer

Tuples are immutable, meaning their elements cannot be changed after the tuple is created. The statement config[1] = 9090 tries to assign to an index, which triggers a TypeError. No automatic rebinding or type-based exception occurs.

To change a value, you must build a new tuple and assign it to the variable.

Exam trap

The trap here is assuming that because lists allow item assignment, tuples might allow it under certain conditions, such as matching types or automatic conversion.

64
MCQeasy

A support technician is running a Python script that parses a configuration file and stores key-value pairs in a dictionary called 'config'. The script then uses these values to set application parameters. The configuration file is optional, and some expected keys may be missing. Currently, the script crashes with a KeyError when accessing a missing key. The technician needs to modify the script to safely retrieve a value or return 'N/A' if a key is missing. The script must remain efficient and readable. Which modification best achieves this?

A.Use config.get(key, 'N/A') instead of direct key access
B.Wrap each access in a try-except block to catch KeyError and assign 'N/A'
C.Use if key in config: value = config[key] else: value = 'N/A'
D.Use config.setdefault(key, 'N/A') before accessing
AnswerA

Using `config.get(key, 'N/A')` returns the supplied default when the key is absent, so no KeyError is raised. This satisfies the requirement to retrieve a value or fall back to 'N/A' for missing optional keys, while keeping the lookup a single, readable expression rather than a multi-line membership test.

Why this answer

`dict.get(key, default)` is the idiomatic Python method for safely retrieving a value from a dictionary without raising a `KeyError`. It returns the default value `'N/A'` when the key is missing, which directly solves the crash while keeping the code concise and readable. This approach is more efficient than exception handling or explicit membership checks because it performs a single hash lookup.

Exam trap

The PCEP exam often tests the distinction between `dict.get()` and `dict.setdefault()`, trapping candidates who think `setdefault()` is a safe retrieval method without realizing it permanently modifies the dictionary by adding the missing key.

How to eliminate wrong answers

Option B is wrong because wrapping each access in a try-except block is verbose, less readable, and slower than using `.get()` due to the overhead of exception handling; it also violates Python's EAFP (Easier to Ask for Forgiveness than Permission) principle in a case where a simple method exists. Option C is wrong because using `if key in config:` performs two dictionary lookups (one for the membership test and one for the retrieval), which is less efficient and more verbose than the single lookup in `.get()`. Option D is wrong because `config.setdefault(key, 'N/A')` modifies the dictionary by inserting the key with the default value if it is missing, which is not the intended behavior—the script should only retrieve a value or return 'N/A' without altering the original dictionary.

65
MCQeasy

A developer needs to store configuration settings as key-value pairs and later retrieve the value for a key that may not exist, providing a default value if the key is missing. Which dictionary method should be used?

A.get()
B.pop()
C.keys()
D.setdefault()
AnswerA

The get() method returns the value for a given key if it exists, otherwise it returns a specified default value (or None if no default is provided). It does not raise an exception for missing keys, making it ideal for this scenario.

Why this answer

The get() method safely retrieves a value for a key and returns a default if the key is absent, without altering the dictionary. Other methods either modify the dictionary or do not directly retrieve values, making them unsuitable for a read-only lookup with a fallback.

Exam trap

The trap here is assuming that setdefault() is equivalent to get() for retrieval, ignoring that setdefault() inserts the missing key into the dictionary, which may cause unintended side effects.

66
MCQmedium

A developer defines a function with the signature def configure(host, port=8080, protocol='http'). A call is made as configure('web01', protocol='https'). Which statement describes what happens?

A.The call fails with a SyntaxError because default parameters must always be passed explicitly when any keyword argument is used.
B.The call succeeds; host receives 'web01', port keeps its default 8080, and protocol receives 'https'.
C.The call fails with a TypeError because a positional argument cannot be combined with a keyword argument.
D.The call succeeds, but 'https' is assigned to port because keyword arguments fill parameters in declaration order.
AnswerB

Positional arguments fill parameters left to right, so 'web01' binds to host. The keyword argument protocol='https' binds by name, skipping port, which therefore retains its default value of 8080. Python allows mixing positional and keyword arguments as long as no parameter receives two values and no required parameter is missing, so this call is valid and behaves exactly as described.

Why this answer

Positional arguments bind to parameters in order, while keyword arguments bind by name regardless of position. Here the single positional value fills host, the keyword protocol fills that named parameter, and port is simply omitted, so it retains its default. The call is valid and produces host='web01', port=8080, protocol='https'.

Exam trap

The trap here is thinking keyword arguments are matched to parameters by their left-to-right position in the call rather than by their explicit names.

67
MCQeasy

A programmer is writing a function that accepts a dictionary of employee records and must return a tuple containing the number of records and the average salary. The function should not modify the input dictionary. Which function definition achieves this?

A.def summarize(employees): count = len(employees) total = sum(employees.keys()) return (count, total / count)
B.def summarize(employees): count = len(employees) total = sum(employees.values()) return (count, total / count)
C.def summarize(employees): count = len(employees) if count == 0: return (0, 0) total = sum(employees.values()) return (count, total / count)
D.def summarize(employees): count = len(employees) total = sum(employees.values()) employees.clear() return (count, total / count)
AnswerC

This function correctly returns a tuple of the number of records and the average salary, and it handles the empty dictionary case by returning (0, 0). It does not modify the input dictionary. The use of employees.values() assumes that the dictionary values are numeric salaries, which aligns with the scenario. This is the most robust and correct implementation.

Why this answer

The correct function must return a tuple with the count and average salary, avoid modifying the input, and handle an empty dictionary gracefully. The chosen option includes a check for zero count, returns a sensible default, and uses dictionary values for the salary sum. The others either fail on empty input, sum the wrong data, or mutate the input.

Exam trap

The trap here is overlooking the empty-dictionary case or accidentally summing keys instead of values, which are common mistakes when working with dictionaries.

68
Multi-Selectmedium

A developer is writing a function that accepts a variable number of arguments and needs to handle them as a tuple. Which two of the following statements about tuples and function arguments are true? (Choose two.)

Select 2 answers
A.Tuples are mutable, so the arguments collected by *args can be modified inside the function.
B.A tuple cannot be passed to a function as a single argument if the function expects multiple parameters.
C.Inside a function, the *args parameter collects extra positional arguments into a tuple.
D.A tuple can be unpacked into positional arguments when calling a function using the * operator.
E.The **kwargs parameter collects extra keyword arguments into a tuple.
AnswersC, D

When a function is defined with *args, any additional positional arguments passed to the function are gathered into a tuple named args. This allows the function to accept an arbitrary number of arguments. The tuple is immutable, so the collected arguments cannot be modified in place. This is a standard Python feature for flexible function signatures.

Why this answer

The *args parameter collects extra positional arguments into a tuple, and the * operator can unpack a tuple into positional arguments in a function call. These two features are often used together to create flexible functions. The **kwargs parameter collects keyword arguments into a dictionary, not a tuple, and tuples are immutable, so their contents cannot be changed.

Understanding these behaviors is essential for working with variable argument lists in Python.

Exam trap

The trap here is mixing up *args and **kwargs, or assuming that tuples are mutable and can be modified inside a function.

69
MCQeasy

A developer writes a function that needs to accept any number of positional arguments and return their sum. Which function definition correctly collects all positional arguments into a tuple named values?

A.def total(*values):
B.def total(**values):
C.def total(*values, **kwargs):
D.def total(values):
AnswerA

The *values parameter collects any number of positional arguments into a tuple named values. Inside the function, sum(values) can add them. This matches the scenario exactly: total(1, 2, 3) yields values as (1, 2, 3). It also allows zero arguments, in which case values is an empty tuple and sum returns 0.

Why this answer

The *args syntax in a function definition packs all positional arguments into a tuple. Using def total(*values) makes values a tuple containing every positional argument passed. Then sum(values) returns their total.

The other definitions either collect keyword arguments into a dictionary, accept only one argument, or add an unnecessary keyword-argument collector that changes the function's behavior.

Exam trap

The trap here is confusing *args and **kwargs, assuming that ** collects positional arguments into a tuple when it actually collects keyword arguments into a dictionary.

70
MCQeasy

What does the following code output? try: x = int('abc') except ValueError: print('Invalid')

A.The program crashes
B.Invalid
C.(Nothing printed)
D.abc
AnswerB

Converting 'abc' with int() raises a ValueError, since the string holds no valid integer literal. The except clause names ValueError specifically, so it catches that exception and executes print('Invalid'). The try block aborts at the failing assignment, meaning nothing else runs before the handler outputs the required text.

Why this answer

The code attempts to convert the string 'abc' to an integer using int(). Since 'abc' is not a valid integer, Python raises a ValueError. The except block catches this specific exception and executes print('Invalid'), so the output is 'Invalid'.

Option B is correct because the exception is handled gracefully without crashing.

Exam trap

The PCEP exam often tests whether candidates understand that a caught exception does not crash the program; the trap here is that some candidates think any error causes a crash, but the except block prevents that.

How to eliminate wrong answers

Option A is wrong because the ValueError is explicitly caught by the except block, preventing the program from crashing; unhandled exceptions cause crashes, but here the exception is handled. Option C is wrong because the except block executes and prints 'Invalid', so something is printed. Option D is wrong because the code does not print the original string 'abc'; it prints the string 'Invalid' from the except block.

71
MCQeasy

What is the result of the following expression? d = {'a': 1} d.get('b', 0)

A.0
B.None
C.KeyError
D.1
AnswerA

dict.get returns the value for the given key, or the supplied default when the key is absent. Since 'b' is not in {'a': 1}, the method returns the default 0 rather than raising KeyError, leaving the dictionary unchanged.

Why this answer

The `get()` method on a dictionary returns the value for the given key if it exists; otherwise, it returns the default value provided as the second argument. Since key `'b'` is not in dictionary `d`, the method returns `0` (the specified default). Option A is correct because `d.get('b', 0)` explicitly supplies a default of `0`.

Exam trap

The PCEP exam often tests the distinction between `dict.get()` (which returns a default or `None`) and direct subscript access `d[key]` (which raises `KeyError`), trapping candidates who confuse the two behaviors.

How to eliminate wrong answers

Option B is wrong because `get()` returns `None` only when no default is provided and the key is missing; here a default of `0` is given. Option C is wrong because `get()` never raises a `KeyError` — that would occur with direct indexing like `d['b']`. Option D is wrong because `1` is the value for key `'a'`, not for key `'b'`.

72
MCQhard

A developer uses a tuple to store immutable configuration data: config = ('localhost', 8080, True). They then write: host, port, secure = config. What is the result of this statement?

A.host becomes 'localhost', port becomes 8080, and secure becomes True.
B.A SyntaxError occurs because the left side must be enclosed in parentheses.
C.A ValueError is raised because tuples cannot be unpacked into multiple variables.
D.host becomes the entire tuple, and port and secure are assigned None.
AnswerA

Tuple unpacking assigns the first element to host, the second to port, and the third to secure, in order. The tuple has exactly three elements, matching the three target variables. This is a concise way to extract multiple values from a tuple. The operation succeeds without error, and the variables receive the corresponding values from the tuple.

Why this answer

Tuple unpacking assigns each element of the tuple to the corresponding variable on the left side, in order. The number of variables must equal the number of elements. In this case, three variables match three elements, so host, port, and secure receive 'localhost', 8080, and True respectively.

No error occurs.

Exam trap

The trap here is assuming that tuple unpacking requires parentheses or that it fails if the tuple contains mixed types.

73
Multi-Selecteasy

Which TWO of the following are valid methods that can be called on a tuple object? (Choose two.)

Select 2 answers
A..pop()
B..index()
C..append()
D..sort()
E..count()
AnswersB, E

.index() searches a tuple for a specified value and returns the zero-based position of its first occurrence, raising ValueError when absent. Tuples support this read-only lookup because it mutates nothing, satisfying the immutability constraint while providing the membership-position query the question requires.

Why this answer

The `.index()` method is a built-in tuple method that returns the index of the first occurrence of a specified value. Tuples are immutable sequences, so they support only non-mutating methods like `.index()` and `.count()`, which do not modify the tuple.

Exam trap

The PCEP exam often tests the distinction between mutable and immutable sequence types, trapping candidates who assume that because lists have methods like `.pop()`, `.append()`, and `.sort()`, tuples must have them too, when in fact tuples only support non-mutating methods like `.index()` and `.count()`.

74
MCQhard

A developer writes a function `def process(data):` that uses a try-except-else-finally block. The try block reads from a file, the except block handles IOError, the else block processes the data, and the finally block closes the file. If no exception occurs, which blocks execute and in what order?

A.try, except, finally
B.try, else, except, finally
C.try, else, finally
D.try, finally
AnswerC

When no exception occurs in the try block, the else block executes after the try block completes successfully. The finally block always executes, regardless of exceptions, so it runs last. The except block is skipped because no exception was raised. Thus the order is try, else, finally.

Why this answer

In a try-except-else-finally structure, the try block runs first. If it completes without raising an exception, the else block executes. The finally block always executes, regardless of whether an exception occurred.

The except block only runs if an exception is raised. Therefore, with no exception, the order is try, else, finally.

Exam trap

The trap here is assuming that the else block runs only if an exception occurs, or that the except block always runs, but the else block is specifically for the no-exception path.

75
MCQmedium

Given the tuple t = (1, 2, 3, 4, 5), which expression returns the last element?

A.t[-1]
B.t[5]
C.t[4]
D.t[0]
AnswerA

Negative indexing counts from the end, so t[-1] returns the final element, 5. This directly satisfies the stem's requirement for the last element, whereas t[0] gives the first and t[5] raises an IndexError because indices stop at 4.

Why this answer

In Python, negative indices count from the end of a sequence. For the tuple t = (1, 2, 3, 4, 5), t[-1] accesses the last element (5), because -1 refers to the final position. This is a standard feature of Python's sequence indexing.

Exam trap

A common trap in PCEP exams is that candidates may use a hardcoded index like t[4] which works for this specific tuple but fails if the tuple length changes. The correct dynamic way is t[-1], which always references the last element regardless of tuple length.

How to eliminate wrong answers

Option B is wrong because t[5] attempts to access index 5, which is out of range for a tuple with indices 0 through 4, raising an IndexError. Option C is wrong because t[4] returns the element at index 4, which is 5, but this is the last element only coincidentally; the question asks for an expression that returns the last element in general, and t[4] is not a robust way to do it if the tuple length changes. Option D is wrong because t[0] returns the first element (1), not the last.

Page 1 of 2 · 80 questions totalNext →

Ready to test yourself?

Try a timed practice session using only Functions, Tuples, Dictionaries and Exceptions questions.