Editor

PCEP practice test

Practise for the PCEP exam with fresh questions in its style, timed, then review every answer.

30 questions · 40 minutes · 70% to pass. Scored in your browser, then every answer is explained.

What it covers

  • Fundamentals
  • Control flow
  • Collections
  • Functions and exceptions
Every question with its answer
  1. Question 1 · Fundamentals

    What is the output of this code?

    print(0b101 + 0o10 + 0x1F)
    • A46
    • B44
    • C28
    • D140

    0b101 is binary 5, 0o10 is octal 8 and 0x1F is hexadecimal 31, so the sum is 44. Reading 0o10 as decimal ten gives the tempting 46.

    Run this code in the editor
  2. Question 2 · Fundamentals

    What is the output of this code?

    print(-7 // 2, -7 % 2, 7 // -2.0)
    • A-3 -1 -3.5
    • B-4 1 -4
    • C-4 1 -4.0
    • D-3 1 -3.0

    // rounds down toward minus infinity, so -7 // 2 is -4, and the result of % takes the sign of the divisor, giving 1. When one operand is a float, // returns a float, so the last value is -4.0.

    Run this code in the editor
  3. Question 3 · Fundamentals

    What is the output of this code?

    base = 2
    print(base ** 3 ** 2 // 100, -base ** 2)
    • A0 -4
    • B5 4
    • C0 4
    • D5 -4

    ** groups from right to left, so base ** 3 ** 2 is 2 ** 9, which is 512, and 512 // 100 is 5. ** also binds tighter than the unary minus, so -base ** 2 is -(2 ** 2), which is -4.

    Run this code in the editor
  4. Question 4 · Fundamentals

    The variable answer holds "7", the value input() returns when a user types 7. What does this code print?

    answer = "7"
    print(answer * 2, int(answer) * 2, sep=" / ", end=".\n")
    • A77 / 14.
    • B14 / 14.
    • C77 14.
    • D7 7 / 14.

    input() always returns a string, so answer * 2 repeats the text to give 77, while int(answer) * 2 is the number 14. sep goes between the printed values and end replaces the usual newline.

    Run this code in the editor
  5. Question 5 · Fundamentals

    Which two of these are valid variable names in Python? Select two.

    • A2nd_place
    • B_total
    • Cclass
    • DPrice2
    • Emy-score

    A name starts with a letter or underscore and continues with letters, digits and underscores, so _total and Price2 are valid. 2nd_place starts with a digit, my-score contains a minus sign, and class is a reserved keyword.

  6. Question 6 · Fundamentals

    What is the output of this code?

    flags = 0b1100
    mask = 0b1010
    print(flags & mask, flags | mask, flags ^ mask, flags >> 2)
    • A14 8 6 3
    • B8 14 6 48
    • C8 14 6 3
    • D8 22 6 3

    & keeps the bits set in both (1000, 8), | keeps bits set in either (1110, 14) and ^ keeps bits that differ (0110, 6). >> 2 shifts right by two places, dividing by 4 to give 3; 48 would be a left shift.

    Run this code in the editor
  7. Question 7 · Control flow

    What is the output of this code?

    temperature = 25
    if temperature > 30:
        print("hot")
    elif temperature > 20:
        print("warm")
    elif temperature > 10:
        print("mild")
    else:
        print("cold")
    • Ahot
    • Bwarm mild
    • Cmild
    • Dwarm

    Python tests the conditions from the top and runs only the first branch whose condition is true. 25 > 20 is the first true test, so the later branches are skipped even though 25 > 10 is also true.

    Run this code in the editor
  8. Question 8 · Control flow

    Which expression creates the list [0, 2, 4, 6, 8]?

    • Alist(range(2, 10, 2))
    • Blist(range(0, 10, 2))
    • Clist(range(0, 8, 2))
    • D[n for n in range(10) if n % 2]

    range(start, stop, step) stops before stop, so range(0, 10, 2) counts 0 to 8 in steps of 2. range(0, 8, 2) stops at 6, range(2, 10, 2) misses 0, and n % 2 is true for the odd numbers.

  9. Question 9 · Control flow

    What is the output of this code?

    attempts = 0
    while attempts < 5:
        attempts += 1
        if attempts == 3:
            break
    else:
        attempts = 100
    print(attempts)
    • A3
    • B100
    • C5
    • D4

    A loop's else block runs only when the loop ends because its condition became false. Here break ends the loop when attempts is 3, so the else block is skipped and 3 is printed.

    Run this code in the editor
  10. Question 10 · Control flow

    What is the output of this code?

    total = 0
    for value in [4, -1, 6, -3, 2]:
        if value < 0:
            continue
        total += value
    else:
        total *= 10
    print(total)
    • A120
    • B12
    • C80
    • D40

    continue skips only the rest of the current pass, so the negative values are left out and total reaches 4 + 6 + 2 = 12. The loop ends without break, so its else block runs and multiplies the total by 10.

    Run this code in the editor
  11. Question 11 · Control flow

    What is the output of this code?

    count = 0
    for row in range(3):
        for col in range(row):
            count += 1
    print(count)
    • A9
    • B6
    • C3
    • D2

    The inner loop runs row times: not at all for row 0, once for row 1 and twice for row 2, so count ends at 3. 9 would be the result if the inner loop also used range(3).

    Run this code in the editor
  12. Question 12 · Control flow

    Which two statements about loops are true? Select two.

    • Acontinue ends the loop and runs its else block.
    • Bbreak exits only the innermost loop that contains it.
    • Cpass skips the rest of the current iteration.
    • Dbreak may appear in an if statement outside any loop.
    • EA loop's else block runs when the loop finishes without break.

    break leaves the nearest enclosing loop only, and a loop's else block runs when no break ended the loop. continue moves on to the next pass, pass does nothing at all, and break outside a loop is a SyntaxError.

  13. Question 13 · Control flow

    What is the output of this code?

    limit = 3
    for i in range(limit):
        limit += 1
        i += 10
    print(limit, i)
    • A6 2
    • B4 11
    • C3 12
    • D6 12

    range(limit) is built once, from the value 3, so the loop runs three times while limit grows to 6. Changing i in the body does not affect the next pass, but after the last pass i keeps its changed value, 2 + 10.

    Run this code in the editor
  14. Question 14 · Control flow

    What is the output of this code?

    values = [0, "", "0", [], None, 0.0]
    truthy = 0
    for item in values:
        if item:
            truthy += 1
    print(truthy)
    • A1
    • B0
    • C2
    • D6

    Zero of any number type, empty strings, empty lists and None all count as false in a condition. The string "0" is not empty, so it is the only true value in the list.

    Run this code in the editor
  15. Question 15 · Collections

    What is the output of this code?

    letters = ["a", "b", "c", "d", "e", "f"]
    print(letters[1:-1:2])
    • A['b', 'd', 'f']
    • B['a', 'c', 'e']
    • C['b', 'd']
    • D['b', 'c', 'd', 'e']

    The slice starts at index 1 ('b'), stops before index -1 (the last item, 'f') and takes every second item, giving 'b' and 'd'. 'f' would be included only if the stop were left out.

    Run this code in the editor
  16. Question 16 · Collections

    What happens when this code runs?

    colors = ["red", "green", "blue"]
    colors.remove("green")
    print(colors[2])
    • AValueError
    • BKeyError
    • CTypeError
    • DIndexError

    remove("green") deletes that value, so the list becomes ['red', 'blue'] with indexes 0 and 1. Index 2 no longer exists, so Python raises IndexError. ValueError would come from removing a value that is not in the list.

    Run this code in the editor
  17. Question 17 · Collections

    What is the output of this code?

    original = [1, 2, 3]
    alias = original
    clone = original[:]
    alias.append(4)
    clone.append(5)
    print(original)
    • A[1, 2, 3, 4]
    • B[1, 2, 3]
    • C[1, 2, 3, 4, 5]
    • D[1, 2, 3, 5]

    alias = original gives the same list a second name, so appending through alias changes original. The slice original[:] makes a new list, so appending 5 to clone leaves original alone.

    Run this code in the editor
  18. Question 18 · Collections

    What is the output of this code?

    record = ("Ana", [90, 85])
    record[1].append(70)
    print(record)
    • A('Ana', [90, 85])
    • B('Ana', [90, 85, 70])
    • C('Ana', [90, 85], 70)
    • D('Ana', 90, 85, 70)

    A tuple's items cannot be replaced, but an item can be a mutable object. record[1] is a list, and appending to it changes that list in place while the tuple still holds the same two objects.

    Run this code in the editor
  19. Question 19 · Collections

    What is the output of this code?

    stock = {"pens": 10, "pads": 4}
    stock["clips"] = 25
    stock["pens"] = 7
    print(len(stock), stock["pens"], stock.get("tape", 0))
    • A4 7 0
    • B3 10 0
    • C3 7 0
    • D3 7 None

    Assigning to a new key adds it and assigning to an existing key replaces its value, so there are 3 keys and "pens" maps to 7. get() returns its second argument, 0, for a missing key instead of raising KeyError.

    Run this code in the editor
  20. Question 20 · Collections

    What is the output of this code?

    title = "  data Science  "
    clean = title.strip()
    clean.upper()
    print(clean.title(), clean.find("S"), len(title) - len(clean))
    • ADATA SCIENCE 5 4
    • BData Science 6 4
    • CData Science 5 2
    • DData Science 5 4

    Strings cannot change, so clean.upper() returns a new string that is thrown away. title() capitalizes each word, find("S") gives index 5 (counting from 0), and strip() removed two spaces from each end.

    Run this code in the editor
  21. Question 21 · Collections

    After which two assignments is t a tuple? Select two.

    • At = (5)
    • Bt = [5]
    • Ct = 5,
    • Dt = {5}
    • Et = tuple([5])

    The comma is what makes a tuple, so 5, is a one-item tuple, and tuple() converts the list into one. (5) is the number 5 in parentheses, [5] is a list and {5} is a set.

  22. Question 22 · Collections

    What is the output of this code?

    grid = [[0] * 3] * 2
    grid[0][1] = 7
    print(grid)
    • A[[0, 7, 0], [0, 0, 0]]
    • B[[0, 7, 0], [0, 7, 0]]
    • C[[7, 7, 7], [0, 0, 0]]
    • D[[0, 0, 0], [0, 7, 0]]

    * 2 repeats a reference to one inner list, so both rows are the same list object and a change through grid[0] shows in both. A comprehension such as [[0] * 3 for row in range(2)] builds separate rows.

    Run this code in the editor
  23. Question 23 · Functions and exceptions

    What is the output of this code?

    def greet(name, greeting="Hello", mark="!"):
        return greeting + ", " + name + mark
    
    print(greet("Mia", mark="?"))
    • AHello, Mia!
    • B?, Mia!
    • CHello, Mia?
    • DHello Mia?

    "Mia" fills name by position, mark is set by keyword, and greeting keeps its default value. Passing "?" as a second positional argument would have replaced greeting instead.

    Run this code in the editor
  24. Question 24 · Functions and exceptions

    What is the output of this code?

    def countdown(n):
        if n == 0:
            return
        print(n, end=" ")
        countdown(n - 1)
    
    print(countdown(3))
    • A3 2 1 None
    • B3 2 1
    • C3 2 1 0 None
    • DNone 3 2 1

    The recursive calls print 3, 2 and 1, and the call with 0 returns before printing. countdown never returns a value, so the outer call returns None, which the last print shows after the numbers.

    Run this code in the editor
  25. Question 25 · Functions and exceptions

    What is the output of this code?

    counter = 10
    
    def bump():
        global counter
        counter += 1
        step = 5
        return counter + step
    
    def shadow():
        counter = 0
        return counter
    
    print(bump(), shadow(), counter)
    • A16 0 10
    • B16 0 0
    • C15 0 11
    • D16 0 11

    global counter lets bump change the module-level name, so it becomes 11 and bump returns 16. In shadow, the assignment creates a local counter that hides the global one without changing it.

    Run this code in the editor
  26. Question 26 · Functions and exceptions

    Which exception does this code raise?

    def average(first, second):
        return (first + second) / 2
    
    print(average(4))
    • ATypeError
    • BValueError
    • CNameError
    • DZeroDivisionError

    Calling a function with fewer arguments than it has parameters without defaults raises TypeError: missing 1 required positional argument: 'second'. Python never fills a missing argument with 0 or None by itself.

    Run this code in the editor
  27. Question 27 · Functions and exceptions

    What is the output of this code?

    try:
        values = [1, 2, 3]
        print(values[3])
    except LookupError:
        print("lookup")
    except IndexError:
        print("index")
    except Exception:
        print("other")
    • Aindex
    • Blookup
    • Cother
    • Dlookup index

    Python runs only the first except branch that matches. IndexError is a subclass of LookupError, so the first branch catches it and the more specific except IndexError never runs. Put specific exceptions before general ones.

    Run this code in the editor
  28. Question 28 · Functions and exceptions

    What is the output of this code?

    def parse(text):
        return int(text)
    
    def safe_total(items):
        total = 0
        for item in items:
            try:
                total += parse(item)
            except ValueError:
                total -= 1
        return total
    
    print(safe_total(["4", "x", "10", "2.5"]))
    • A15
    • B3
    • C14
    • D12

    The ValueError raised inside parse travels up to the caller, where except handles it and the loop carries on. int("2.5") also raises ValueError, since int() does not accept a decimal string, so the total is 4 - 1 + 10 - 1.

    Run this code in the editor
  29. Question 29 · Functions and exceptions

    What is the output of this code?

    def add_item(item, basket=[]):
        basket.append(item)
        return basket
    
    add_item("egg")
    print(add_item("milk"), add_item("tea", []))
    • A['milk'] ['tea']
    • B['egg', 'milk'] ['egg', 'milk', 'tea']
    • C['egg', 'milk'] ['tea']
    • D['milk'] ['milk', 'tea']

    The default list is created once, when def runs, and every call that leaves out basket shares it. So the second call appends to the list that already holds 'egg', while the call that passes [] gets a list of its own.

    Run this code in the editor
  30. Question 30 · Functions and exceptions

    Which two statements about Python's built-in exceptions are true? Select two.

    • AKeyboardInterrupt is a subclass of Exception.
    • BValueError is a subclass of TypeError.
    • CZeroDivisionError is a subclass of ArithmeticError.
    • Dexcept Exception: also catches SystemExit.
    • EKeyError and IndexError are both subclasses of LookupError.

    ZeroDivisionError comes under ArithmeticError, and KeyError and IndexError come under LookupError. KeyboardInterrupt and SystemExit derive from BaseException directly, so except Exception misses them, and ValueError and TypeError are separate branches.

Next: the PCAP practice test, a free Python certification exam with a certificate anyone can check, or MCQ practice by topic.

PCEP and PCAP are certifications of the Python Institute (OpenEDG), which is not affiliated with this website and does not endorse it. These practice questions are written for this site in the style of those exams; they are not the exams’ own questions.