Python Institute · Free Practice Questions · Last reviewed May 2026
24real exam-style questions organised by domain, each with the correct answer highlighted and a plain-English explanation of why it's right — and why the others are wrong.
29% of exam · 6 sample questions below
A programmer writes code that uses a while loop to process user input until the user types 'exit'. The code currently prints 'Done' after the loop, but it never exits. What is the most likely cause?
The loop condition is 'while True'
The print statement is indented incorrectly
The input function is called outside the loop
The variable controlling the loop is not updated inside the loop
The loop condition depends on a variable that must change each iteration to eventually become false. If that variable is never reassigned inside the loop body, the condition stays true forever, so the loop never terminates and 'Done' is never reached.
A list of numbers is defined as nums = [1, 2, 3, 4, 5]. Which expression returns the last element?
nums[5]
nums[-1]
Negative indexing counts from the end of the sequence, so nums[-1] refers to the final element, 5. This satisfies the stem's requirement for retrieving the last element without computing its index from the list length.
nums[0]
nums[-2]
A developer writes the following code snippet:
for i in range(3):
for j in range(2):
if i == j:break else:
print(i, 'outer')
What is the output?
0 outer\n2 outer
2 outer
The inner loop breaks only when i equals j, so for i=0 and i=1 the else clause is skipped. For i=2, j never equals 2, so the inner loop completes and the else runs, printing '2 outer'.
0 outer\n1 outer\n2 outer
No output
Given the code: x = [1, 2, 3] y = x y.append(4)
print(x)
What is the output?
Error
[1, 2, 3]
[1, 2, 3, 4]
Assignment binds y to the same list object as x, not a copy. Calling append mutates that shared object in place, so the single list now holds four elements and printing x reflects the change.
[1, 2, 3, 4, 5]
A programmer wants to create a list of even numbers from 0 to 10 inclusive. Which list comprehension is correct?
[x for x in range(0,11) if x%2==0]
The comprehension iterates over `range(0,11)`, whose stop value is exclusive, so it yields 0 through 10 inclusive as the stem requires. The filter `x%2==0` then retains only even values, producing `[0,2,4,6,8,10]` in a single expression without needing an explicit append loop.
[x for x in range(0,10) if x%2==0]
[x for x in range(0,11) if x%2]
[x for x in range(0,11) if x%2==1]
Which THREE of the following are valid ways to create a list with elements 10, 20, 30?
my_list = [x for x in (10,20,30)]
The list comprehension iterates over the tuple (10,20,30) and appends each element, producing a new list containing exactly those three values. It is a valid construction, though more verbose than a literal, and yields the required elements in order.
my_list = list((10, 20, 30))
The list() constructor accepts any iterable, including the tuple (10, 20, 30), converting it into a new list with those elements. This satisfies the stem's requirement for a valid list-creation method producing exactly 10, 20 and 30.
my_list = list(10, 20, 30)
my_list = [10; 20; 30]
my_list = [10, 20, 30]
A list literal written with square brackets and comma-separated values directly constructs the list containing 10, 20 and 30. This is the most straightforward valid creation method, requiring no iteration or conversion, and produces exactly the required elements in order.
Want more Control Flow, Loops, Lists and Logic practice?
Practice this domain18% of exam · 6 sample questions below
Which of the following is the correct way to define a function that takes no arguments and returns the value 42?
function f(): return 42
def f() return 42
def f: return 42
def f(): return 42
The empty parameter list satisfies the no-arguments constraint, and the bare `return 42` supplies the required value. Python permits a single-line suite after the colon, so this definition is syntactically valid and returns the integer 42 when called as `f()`.
A program uses a variable named 'list' that shadows the built-in list type. Later, the code tries to create a new list using list([1,2,3]) but gets a TypeError. What is the most likely cause?
The argument [1,2,3] is invalid because it contains integers.
The variable 'list' is now an integer or other non-callable type.
Rebinding the name 'list' to a non-callable value, such as an integer, means list([1,2,3]) attempts to call that object, raising TypeError. The built-in list type is shadowed in that scope, so the original constructor is no longer reachable via that name.
The list constructor expects a tuple, not a list.
The code is missing an import for the list type.
A programmer writes: x = 5; y = 2; result = x / y. What is the type of result?
int
float
The division operator in Python 3 always performs true division, returning a float regardless of whether operands are integers. So 5 / 2 yields 2.5, typed as float, not int. Floor division (//) would return an integer instead.
str
complex
Which of the following statements about Python indentation is true?
Indentation is optional but recommended.
You can mix tabs and spaces freely.
Indentation must be consistent within a block.
Python uses indentation to delimit blocks, and every statement within the same block must share identical leading whitespace. Mixing tabs and spaces or varying indent width within one block raises an IndentationError, so consistency is mandatory rather than stylistic.
Indentation only matters for loops and conditionals.
A developer needs to iterate over the indices of a list named 'items' and print each index and its corresponding value. Which loop construct is most appropriate?
for val in items: print(items.index(val), val)
for i in range(len(items)): print(i, items[i])
for i, val in enumerate(items): print(i, val)
enumerate() yields index-value pairs directly, avoiding manual counter maintenance or range(len(items)) indexing. It satisfies the requirement to print both the index and its corresponding value in one clean iteration, which is the idiomatic and most readable construct for this task.
for i in items: print(i)
What is the output of: print(2 ** 3 ** 2)?
512
The exponentiation operator ** is right-associative, so 3 ** 2 evaluates first to 9, then 2 ** 9 yields 512. Left-to-right evaluation would give 64, but Python's grammar groups the rightmost operation first, producing 512.
12
64
256
Want more Computer Programming and Python Fundamentals practice?
Practice this domain25% of exam · 6 sample questions below
A developer writes the following code: x = 5; y = 2; print(x // y). What is the output?
1
2
The // operator performs floor division, dividing 5 by 2 and rounding the result down to the nearest integer. Since both operands are integers, Python returns an int, and 2.5 floors to 2, matching the printed output.
2.0
2.5
A junior developer writes: x = 10; y = 3; print(x % y). What will be printed?
3.33
1
The modulo operator returns the remainder after integer division, so 10 % 3 evaluates to 1 because 3 divides into 10 three times with 1 left over. This satisfies the stem's requirement to predict the printed output of the expression.
0
3
A developer needs to convert a string '25' to an integer and then add 10. Which code correctly performs this?
print(int('25') + 10)
Correct conversion and addition.
print('25' + 10)
print(int('25') + '10')
print('25' + str(10))
What is the correct way to read a floating-point number from user input and store it in a variable?
x = input(float())
x = input() as float
x = float(input())
`float(input())` converts the entered string directly into a floating-point value, satisfying the requirement to read a number rather than text. `input()` always returns a string, so wrapping it in `float()` performs the necessary type conversion in one step, storing the numeric result in `x`.
x = input().float()
A developer wants to assign the value 3.14 to a variable and later change it to the integer 3. Which of the following is true?
This is allowed only if the variable was declared as a float.
This causes a TypeError because you cannot change types.
This is allowed because Python is dynamically typed.
Python variables are unbound names, so rebinding `pi` from the float 3.14 to the integer 3 is legal; the interpreter checks types at runtime, not at declaration. This satisfies the stem's requirement that the same name later hold a different type, which dynamic typing permits.
This is allowed only if you use the int() function during assignment.
Which of the following is a valid variable name in Python?
my-var
2nd_place
_count
A leading underscore is a legal identifier character in Python, and _count contains no spaces, digits at the start, or reserved keywords. It therefore satisfies Python's naming rules, unlike names beginning with a digit or using punctuation.
class
Want more Data Types, Variables, Basic I/O and Operators practice?
Practice this domain28% of exam · 6 sample questions below
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?
Return None if any non-numeric value is encountered.
Use try-except to ignore non-numeric values and proceed with the remaining numbers.
Convert all values to string and concatenate them.
Check that all items are numeric before calculation, and raise TypeError otherwise.
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.
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?
It returns an empty string.
It raises a KeyError.
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`.
It returns None.
It checks the 'in' operator automatically and returns False.
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?
Create a copy of the dictionary at the start: `data = data.copy()`
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.
Add the key, then delete it at the end.
Modify directly; changes to mutable objects are local only.
Convert the dictionary to a tuple before processing.
A developer writes a function that takes a tuple as an argument and tries to modify an element inside the tuple. What happens?
The code raises a TypeError.
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.
The tuple is converted to a list automatically.
The first element is modified successfully.
The code raises a ValueError.
Which TWO of the following statements about tuples in Python are true?
Tuples are always hashable.
Tuples can be used as dictionary keys if all elements are hashable.
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.
Tuples do not support indexing.
Tuples can only contain immutable objects.
Tuples are immutable sequences.
Tuples cannot be modified after creation: no item assignment, append, or removal. This immutability is the defining property distinguishing tuples from lists, and it also makes them hashable, so they can serve as dictionary keys.
Order the steps to create and use a list in Python.
1. Create a list with brackets: my_list = [] 2. Assign it to a variable: my_list = [1, 2, 3] 3. Access elements by index: print(my_list[0]) 4. Modify elements by assignment: my_list[0] = 10 5. Grow the list with methods: my_list.append(4)
This is correct because you first create an empty list or a list literal, assign it to a variable, then you can access elements, modify them, and finally grow the list using methods like append.
1. Access elements by index: my_list[0] 2. Create a list with brackets: [] 3. Assign it to a variable: my_list = [] 4. Modify elements by assignment: my_list[0] = 10 5. Grow the list with methods: my_list.append(4)
1. Create a list with brackets: my_list = [] 2. Access elements by index: print(my_list[0]) 3. Assign it to a variable: my_list = [1, 2, 3] 4. Modify elements by assignment: my_list[0] = 10 5. Grow the list with methods: my_list.append(4)
1. Create a list with brackets: my_list = [] 2. Assign it to a variable: my_list = [1, 2, 3] 3. Grow the list with methods: my_list.append(4) 4. Access elements by index: print(my_list[0]) 5. Modify elements by assignment: my_list[0] = 10
Want more Functions, Tuples, Dictionaries and Exceptions practice?
Practice this domainThe PCEP exam has 30 questions and must be completed in 45 minutes. The passing score is 700/1000.
Scenario-based questions covering exam objectives with detailed answer explanations.
The exam covers 4 domains: Control Flow, Loops, Lists and Logic, Computer Programming and Python Fundamentals, Data Types, Variables, Basic I/O and Operators, Functions, Tuples, Dictionaries and Exceptions. Questions are weighted by domain — higher-weight domains appear more on your actual exam.
No. These are original exam-style practice questions written against the official Python Institute PCEP exam objectives. They are not copied from the real exam. Courseiva focuses on genuine understanding, not memorisation of braindumps.
Courseiva tracks your accuracy per domain and routes you toward weak areas automatically. Free, no account required.