PCAP practice test
Practise for the PCAP exam with fresh questions in its style, timed, then review every answer.
40 questions · 65 minutes · 70% to pass. Scored in your browser, then every answer is explained.
What it covers
- Modules and packages
- Exceptions
- Strings
- Object-oriented programming
- Generators, closures and more
Every question with its answer
Question 1 · Modules and packages
What is the output of this code?
import math as m from math import floor, ceil print(floor(-2.5), ceil(-2.5), m.trunc(-2.5))
- A-2 -3 -2
- B-3 -2 -2
- C-3 -2 -3
- D-2 -2 -3
Run this code in the editorfloor()rounds down to -3 andceil()rounds up to -2.trunc()drops the fractional part, which for a negative number moves toward zero, so it also gives -2. The aliasmand thefromimport reach the same module.Question 2 · Modules and packages
Which two statements about importing are true? Select two.
- A
import math as mmakes bothmandmathavailable. - BAfter
import math, the namesqrton its own is not defined. - CA module's code runs again each time the same program imports it.
- DThe code in a package's
__init__.pyruns when the package is first imported. - EThe
__pycache__folder holds copies of each module's source code.
A plain
import mathbinds only the namemath, so you writemath.sqrt, and importing a package runs its__init__.py. An alias binds onlym, a module runs once per program (later imports reuse it), and__pycache__holds compiled bytecode.- A
Question 3 · Modules and packages
This code is saved as
tools.py. What appears when another program runsimport tools?def helper(): return 42 print("loading tools") if __name__ == "__main__": print("testing helper:", helper())
- A
loading tools, thentesting helper: 42 - BNothing, because importing only defines names
- COnly
loading tools - DOnly
testing helper: 42
Importing runs the module's top-level code, so the first
Run this code in the editorprintruns. Inside an imported module__name__is"tools", not"__main__", so the guarded test runs only when the file itself is the program being run.- A
Question 4 · Modules and packages
Which call can never return the value
10?- Arandom.randint(1, 10)
- Brandom.choice([5, 10])
- Crandom.sample(range(1, 11), 1)[0]
- Drandom.randrange(1, 10)
randrange(1, 10)picks fromrange(1, 10), which stops before 10.randint(1, 10)includes both ends, and the other two pick from collections that contain 10.Question 5 · Modules and packages
Which function returns the Python version as a tuple of strings, such as
('3', '13', '5')?- Aplatform.python_version_tuple()
- Bplatform.python_version()
- Cplatform.version()
- Dplatform.python_implementation()
python_version_tuple()returns the major, minor and patch numbers as a tuple of strings.python_version()returns one string such as'3.13.5',version()describes the operating system, andpython_implementation()names the interpreter, such as'CPython'.Question 6 · Modules and packages
What is the output of this code?
import math print(math.factorial(4), math.hypot(6, 8), math.sqrt(16), 7 // 2.0)
- A24 10.0 4.0 3.0
- B24 10 4 3
- C24 10.0 4 3
- D24 10.0 4.0 3.5
Run this code in the editorfactorial()returns an int, whilehypot()andsqrt()always return floats, even for whole results. Floor division with a float operand also gives a float, so7 // 2.0is 3.0, not 3.5.Question 7 · Exceptions
What is the output of this code?
def load(value): try: number = int(value) except ValueError: print("bad", end=" ") return -1 else: print("ok", end=" ") return number finally: print("done", end=" ") print(load("7"), load("x"))
- Aok done 7 bad done -1
- Bok done bad done 7 -1
- Cok bad 7 -1
- Dok done bad 7 -1
Run this code in the editorfinallyruns on the way out of the function even afterreturn, so each call prints its branch word and thendone.printevaluates both calls before it prints anything itself, so the return values 7 and -1 come last.Question 8 · Exceptions
What is the output of this code?
def check(age): if age < 0: raise ValueError("negative", age) return age try: check(-3) except (TypeError, ValueError) as error: print(error.args, len(error.args))
- A('negative', -3) 1
- B('negative -3',) 1
- Cnegative -3 2
- D('negative', -3) 2
Every argument passed to an exception's constructor is stored in its
Run this code in the editorargstuple, so it holds two items. A tuple of classes inexceptcatches any of them, andas errornames the exception object.Question 9 · Exceptions
What is the output of this code?
class AppError(Exception): pass class LoginError(AppError): def __init__(self, user): super().__init__(f"cannot log in: {user}") self.user = user try: raise LoginError("sam") except AppError as problem: print(type(problem).__name__, problem, problem.user)
- AAppError cannot log in: sam sam
- BLoginError sam sam
- CLoginError cannot log in: sam sam
- DLoginError ('cannot log in: sam',) sam
Run this code in the editorexcept AppErroralso catches its subclasses, but the object is still a LoginError, sotype(problem).__name__names the subclass. Printing an exception shows the message passed tosuper().__init__(), anduseris an ordinary attribute.Question 10 · Exceptions
What is the output of this code?
def risky(): try: return 10 / 0 except ArithmeticError: print("inner", end=" ") raise try: risky() except ZeroDivisionError: print("outer ZeroDivisionError") except ArithmeticError: print("outer ArithmeticError")
- Ainner outer ZeroDivisionError
- Binner outer ArithmeticError
- Couter ZeroDivisionError
- Dinner
A bare
Run this code in the editorraiseinsideexceptre-raises the same exception object, which is still a ZeroDivisionError. The caller's first matching branch isexcept ZeroDivisionError, even though the inner handler caught it as an ArithmeticError.Question 11 · Exceptions
Which exception does this code raise?
def set_speed(speed): assert 0 <= speed <= 120, "speed out of range" return speed print(set_speed(60), set_speed(150))
- AValueError
- BAssertionError
- CRuntimeError
- DTypeError
Run this code in the editorassertraises AssertionError, with the text after the comma as its message, when its condition is false. Nothing is printed, becauseprintneeds both values before it runs and the second call fails.Question 12 · Exceptions
Which two statements about handling exceptions are true? Select two.
- AAn
elsebranch afterexceptruns only when thetryblock raised nothing. - B
finallyruns only when thetryblock raised an exception. - CA bare
raiseoutside anyexceptblock re-raises the last handled error. - DA bare
except:must be the last of theexceptbranches. - ECode that calls a function cannot catch an exception raised inside it.
elseruns when thetryblock finished without an exception, and a bareexcept:placed before other branches is a SyntaxError.finallyalways runs, a bareraisewith no active exception raises RuntimeError, and exceptions travel up to the caller.- AAn
Question 13 · Exceptions
What is the output of this code?
errors = [KeyError("k"), IndexError(5), ZeroDivisionError(), ValueError("v")] labels = [] for error in errors: try: raise error except LookupError: labels.append("L") except ArithmeticError: labels.append("A") except Exception: labels.append("E") print("".join(labels))
- ALEAE
- BLLAE
- CLLEE
- DELAE
KeyError and IndexError are both subclasses of LookupError, ZeroDivisionError is a subclass of ArithmeticError, and ValueError matches only the general
Run this code in the editorExceptionbranch.raiseaccepts an exception object that already exists.Question 14 · Exceptions
What is the output of this code?
class StockError(Exception): def __init__(self, item, left): super().__init__(item) self.left = left def __str__(self): return f"{self.args[0]} has {self.left} left" try: raise StockError("pens", 2) except Exception as error: print(error, error.args)
- Apens has 2 left ('pens', 2)
- B('pens', 2) ('pens', 2)
- Cpens has 2 left ('pens',)
- Dpens ('pens',)
Run this code in the editorargsholds what was passed toException.__init__(), which here is onlyitem, so it is the one-item tuple('pens',).printuses the overridden__str__, which builds the message fromargs[0]and the extra attribute.Question 15 · Strings
What is the output of this code?
print(ord("A"), chr(ord("a") + 2), ord("b") - ord("a"))
- A65 b 1
- B97 c 1
- C65 c 2
- D65 c 1
Run this code in the editorord()gives a character's code point andchr()turns a code point back into a character. Uppercase'A'is 65 and lowercase letters run in order from 97, so 97 + 2 is'c'and'b'is 1 after'a'.Question 16 · Strings
What is the output of this code?
words = ["pear", "Apple", "apple", "banana"] print(sorted(words), "Zebra" < "apple", "10" < "9")
- A['Apple', 'apple', 'banana', 'pear'] True True
- B['apple', 'Apple', 'banana', 'pear'] False False
- C['Apple', 'apple', 'banana', 'pear'] False True
- D['Apple', 'apple', 'banana', 'pear'] True False
Strings compare character by character by code point, and every uppercase letter (65-90) comes before every lowercase one (97-122), so
Run this code in the editor'Zebra' < 'apple'. Digits compare as characters too, and'1'comes before'9', so'10' < '9'is true.Question 17 · Strings
What is the output of this code?
line = "red,,green,blue" parts = line.split(",") print(len(parts), "-".join(parts), " a b ".split())
- A3 red-green-blue ['a', 'b']
- B4 red--green-blue ['', 'a', 'b', '']
- C4 red--green-blue ['a', 'b']
- D3 red-green-blue ['', 'a', 'b', '']
With a separator,
Run this code in the editorsplit(",")keeps the empty string between the two commas, giving 4 parts, andjoin()puts a hyphen between every pair. With no argument,split()splits on runs of whitespace and drops empty strings.Question 18 · Strings
What is the output of this code?
path = "docs/2026/report.final.txt" print(path.find("/"), path.rfind("."), path.find("draft"), path[path.rfind("/") + 1:])
- A4 16 -1 report.final.txt
- B5 23 -1 report.final.txt
- C4 22 -1 /report.final.txt
- D4 22 -1 report.final.txt
Run this code in the editorfind()returns the index of the first match andrfind()the index of the last, both counting from 0, and both return -1 when there is no match. Slicing from one past the last/leaves the file name.Question 19 · Strings
This code prints
-1first. Which exception does it raise next?code = "PY-2026" print(code.find("X")) print(code.index("X"))
- AIndexError
- BValueError
- CKeyError
- DTypeError
Run this code in the editorfind()andindex()search the same way, but when the text is missingfind()returns -1 whileindex()raises ValueError: substring not found. IndexError is for a position outside a sequence.Question 20 · Strings
Which two statements about text encoding are true? Select two.
- AUTF-8 stores every character in exactly one byte.
- BA code point is the number that Unicode assigns to a character.
- CASCII defines 256 characters.
- D
len()of a string counts bytes, not characters. - EUTF-8 stores each ASCII character as one byte with its ASCII value.
Unicode gives every character a number, its code point, and UTF-8 encodes the 128 ASCII characters as single bytes with their ASCII values, so plain ASCII text is valid UTF-8. Other characters take 2 to 4 bytes, and
len()counts characters.Question 21 · Strings
What is the output of this code?
word = "abcdefgh" print(word[5:2], word[::-2], word[-3:1:-1], sep="|")
- A|hfdb|fedc
- B|geca|fedc
- C|hfdb|fedcb
- Dfed|hfdb|fedc
With a positive step, a slice whose start is after its stop is empty, so
Run this code in the editorword[5:2]is''. A step of -2 from the end takes h, f, d and b, andword[-3:1:-1]runs backwards from index 5 down to, but not including, index 1.Question 22 · Strings
What is the output of this code?
values = ["2026", "v2", "abc", "4.5", ""] print([text for text in values if text.isalnum()], "4.5".isdigit(), "".isalpha())
- A['2026', 'v2', 'abc', ''] False True
- B['2026', 'v2', 'abc'] True False
- C['2026', 'v2', 'abc'] False False
- D['v2'] False False
Run this code in the editorisalnum()is true when every character is a letter or a digit, so the dot in'4.5'fails it, andisdigit()rejects the dot too.isalnum(),isalpha()andisdigit()all return False for an empty string.Question 23 · Object-oriented programming
What is the output of this code?
class Counter: total = 0 def __init__(self): Counter.total += 1 self.id = Counter.total a = Counter() b = Counter() print(a.id, b.id, a.total, Counter.total)
- A1 2 1 2
- B1 1 1 2
- C0 1 2 2
- D1 2 2 2
Run this code in the editortotalis a class variable shared by all instances, and each constructor call adds 1 to it, so it ends at 2.a.totalfinds no instance attribute calledtotaland reads the class one, whileidis stored on each object.Question 24 · Object-oriented programming
This code prints
North Highfirst. Which exception does it raise next?class Person: def __init__(self, name): self.name = name class Student(Person): def __init__(self, name, school): self.school = school pupil = Student("Lea", "North High") print(pupil.school) print(pupil.name)
- AAttributeError
- BTypeError
- CNameError
- DKeyError
Run this code in the editorStudentdefines its own__init__, which replaces the inherited one, and it never callssuper().__init__(name). Soself.nameis never set, and reading it raises AttributeError.Question 25 · Object-oriented programming
What is the output of this code?
class Book: shelf = "A" def __init__(self, title): self.title = title novel = Book("Dune") novel.pages = 412 print(novel.__dict__, "shelf" in Book.__dict__, "shelf" in novel.__dict__)
- A{'title': 'Dune', 'pages': 412, 'shelf': 'A'} True True
- B{'title': 'Dune'} True False
- C{'title': 'Dune', 'pages': 412} True False
- D{'title': 'Dune', 'pages': 412} False False
An object's
Run this code in the editor__dict__holds only its own instance attributes, including ones added after it was created, such aspages. The class variableshelflives in the class's__dict__, and the object reaches it through the class.Question 26 · Object-oriented programming
Which exception does this code raise?
class Greeter: def hello(): return "hi" greeter = Greeter() print(greeter.hello())
- AAttributeError
- BTypeError
- CNameError
- DSyntaxError
Calling a method through an object passes the object as the first argument.
Run this code in the editorhellohas no parameter to receive it, so Python raises TypeError: it takes 0 positional arguments but 1 was given. The fix isdef hello(self):.Question 27 · Object-oriented programming
What is the output of this code?
class Vault: def __init__(self): self.__code = 1234 self._hint = "year" vault = Vault() print(list(vault.__dict__))
- A['_Vault__code', '_hint']
- B['__code', '_hint']
- C['_hint']
- D['_Vault__code', '_Vault_hint']
A name with two leading underscores inside a class is renamed to
Run this code in the editor_ClassName__name, so__codeis stored as_Vault__code. One leading underscore is only a convention and changes nothing, and private attributes still appear in__dict__.Question 28 · Object-oriented programming
What is the output of this code?
class Animal: def __init__(self, name): self.name = name def speak(self): return "..." def intro(self): return f"{self.name} says {self.speak()}" class Dog(Animal): def speak(self): return "woof" print(Animal("Generic").intro(), "|", Dog("Rex").intro())
- AGeneric says ... | Rex says ...
- BGeneric says woof | Rex says woof
- CGeneric says ... | Rex says woof
- D... | woof
Run this code in the editorintrois inherited, butself.speak()is looked up on the actual object, and for a Dog that finds the overridingspeak. The same inherited method gives a different result for each class: that is polymorphism.Question 29 · Object-oriented programming
What is the output of this code?
class Base: def who(self): return "Base" class Left(Base): def who(self): return "Left>" + super().who() class Right(Base): def who(self): return "Right>" + super().who() class Child(Left, Right): pass print(Child().who())
- ALeft>Base
- BLeft>Right>Base
- CLeft>Base>Right>Base
- DRight>Left>Base
Run this code in the editorsuper()follows the method resolution order of the object's class,Child, Left, Right, Base, object, not the parent named in the class statement. Sosuper()inLeftreachesRight, andBaseruns once, at the end.Question 30 · Object-oriented programming
What is the output of this code?
class Shape: pass class Square(Shape): pass s = Square() t = Square() print(isinstance(s, Shape), issubclass(Shape, Square), s is t, type(s) is type(t))
- AFalse False False True
- BTrue True False True
- CTrue False True True
- DTrue False False True
A Square object is also an instance of its superclass Shape, but Shape is not a subclass of Square.
Run this code in the editoriscompares identity:sandtare two different objects, while their type is the same class object.Question 31 · Object-oriented programming
What is the output of this code?
class Money: def __init__(self, amount): self.amount = amount def __add__(self, other): return Money(self.amount + other.amount) def __str__(self): return f"${self.amount}" total = Money(5) + Money(7) print(total, str(total) == "$12", total.amount * 2)
- A$12 True $24
- B12 True 24
- C$12 False 24
- D$12 True 24
Run this code in the editor+between two Money objects calls__add__, which returns a new Money holding 12.print()andstr()both use__str__, so they agree, andtotal.amount * 2is ordinary int arithmetic.Question 32 · Object-oriented programming
Which two expressions are
Truefor these classes? Select two.class Vehicle: wheels = 4 class Bike(Vehicle): def __init__(self): self.wheels = 2
- Ahasattr(Bike, 'wheels')
- BBike.__bases__ == (object,)
- CBike().wheels == Vehicle.wheels
- DBike.__name__ == 'Vehicle'
- E'wheels' in Bike().__dict__
Run this code in the editorhasattr()on the class findswheelsinherited from Vehicle, and the constructor stores a separatewheelsin each Bike object's__dict__.Bike.__bases__is(Vehicle,), a Bike object has 2 wheels, not 4, and__name__is'Bike'.Question 33 · Object-oriented programming
What is the output of this code?
class Team: members = [] def __init__(self, name): self.name = name def join(self, person): self.members.append(person) red = Team("red") blue = Team("blue") red.join("Ana") blue.join("Ben") print(red.members, blue.members is Team.members)
- A['Ana'] False
- B['Ana', 'Ben'] False
- C['Ana', 'Ben'] True
- D['Ana'] True
Run this code in the editorself.members.append()does not assign toself.members: it finds the class's list and changes it, so every Team shares one list. Assigningself.members = []in__init__would give each team its own.Question 34 · Object-oriented programming
This file is run directly. Which two statements about its classes are true? Select two.
class Engine: pass class Car: def __init__(self): self.engine = Engine()
- A
Caris a subclass ofEngine. - B
Car.__module__is'__main__'. - CEach
Carobject has its ownEngineobject. - D
Engine.__bases__is an empty tuple. - E
Car.__name__is'Car()'.
A class defined in the file being run belongs to the module
Run this code in the editor__main__, and the constructor creates a new Engine for every Car, which is composition, not inheritance. A class with no listed parent still has(object,)as its__bases__.- A
Question 35 · Generators, closures and more
Which two statements about
open()modes are true? Select two.- AMode
"w"empties an existing file before writing. - BMode
"a"writes new text at the start of the file. - CMode
"r"creates the file if it does not exist. - DMode
"x"replaces a file that already exists. - EReading in mode
"rb"returnsbytesobjects.
"w"truncates the file to zero length first, and binary modes read and writebytes."a"adds to the end,"r"raises FileNotFoundError for a missing file, and"x"raises FileExistsError instead of replacing a file.- AMode
Question 36 · Generators, closures and more
Which expression gives the list
[1, 4, 9]?numbers = [1, 2, 3]
- Amap(lambda n: n ** 2, numbers)
- Blist(map(lambda n: n ** 2, numbers))
- Clist(filter(lambda n: n ** 2, numbers))
- D[lambda n: n ** 2 for n in numbers]
Run this code in the editormap()applies the lambda to every item but returns a lazy map object, solist()is needed to get a list.filter()keeps the items for which the lambda gives a true value, here all of them, and the comprehension builds a list of three functions.Question 37 · Generators, closures and more
What is the output of this code?
def make_counter(start): count = start def step(): nonlocal count count += 1 return count return step first = make_counter(10) second = make_counter(0) first() print(first(), second(), first())
- A12 1 13
- B11 1 12
- C12 11 13
- D11 1 11
Each call to
Run this code in the editormake_countercreates a newcountthat itsstepclosure keeps alive, so the two counters are independent.firstwas already called once, so the next calls give 12 and 13, whilesecondstarts from 0.Question 38 · Generators, closures and more
What is the output of this code?
callbacks = [] for n in range(3): callbacks.append(lambda: n * 10) print([callback() for callback in callbacks])
- A[0, 10, 20]
- B[0, 0, 0]
- C[30, 30, 30]
- D[20, 20, 20]
A lambda looks up
Run this code in the editornwhen it is called, not when it is created. All three run after the loop, whennis 2, so each returns 20. A default argument,lambda n=n: n * 10, would capture each value.Question 39 · Generators, closures and more
What is the output of this code?
def countdown(n): while n > 0: yield n n -= 2 steps = countdown(7) print(next(steps), list(steps), list(steps))
- A7 [7, 5, 3, 1] [7, 5, 3, 1]
- B7 [5, 3, 1] [5, 3, 1]
- C7 [5, 3, 1] []
- D7 [5, 3, 1, -1] []
A generator produces each value once.
Run this code in the editornext()takes 7, the firstlist()collects the remaining 5, 3 and 1, and the generator is then exhausted, so the secondlist()is empty. The loop stops before -1 because the condition is checked first.Question 40 · Generators, closures and more
What is the output of this code?
with open("notes.txt", "w") as file: file.write("one\ntwo\n") file.write("three") with open("notes.txt") as file: first = file.readline() rest = file.readlines() print(repr(first), rest)
- A'one' ['two', 'three']
- B'one\n' ['one\n', 'two\n', 'three']
- C'one\n' ['two\n', 'three']
- D'one\ntwo\nthree' []
Run this code in the editorreadline()reads one line and keeps its newline character, whichrepr()shows as\n.readlines()continues from where reading stopped, and the last line has no newline because none was written.
Next: the PCEP 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.