PCEP cheat sheet
The whole of PCEP-30-02 on one page, grouped by its four blocks - fundamentals, control flow, data collections, functions and exceptions. Every output was printed by Python 3.14.4, and every row is one the exam actually asks about.
- Python3.14.4
- OSUbuntu 26.04 LTS
- pip25.1.1
- Commands50
- Reviewed23 August 2026
Block 1: Fundamentals (18%)
-
sys.implementation.nameWhich Python is running. CPython compiles to bytecode and interprets the bytecode - the answer to "compiled or interpreted?" is both.
bash Example session python3 -c 'import sys; print(sys.implementation.name, sys.version_info)'cpython sys.version_info(major=3, minor=14, micro=4, releaselevel='final', serial=0) -
a SyntaxError prints nothing at allThe whole file is compiled before any of it runs, so a syntax error means no output - not even from correct lines above it.
bash Example session python3 ~/py/lexical.py File "/home/sysadmin/py/lexical.py", line 2 print("this one is not" ^SyntaxError: '(' was never closed[exit 1] -
keyword.kwlist35 reserved words on Python 3.14. True, False and None are among them; print is not.
bash Example session python3 -c 'import keyword; print(len(keyword.kwlist)); print(keyword.kwlist)'35['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'] -
TabErrorMixing tabs and spaces has its own exception class - a subclass of IndentationError, itself a subclass of SyntaxError. Practice tests ask for it by name.
bash Example session python3 ~/py/i3.py File "/home/sysadmin/py/i3.py", line 3 print("spaces")TabError: inconsistent use of tabs and spaces in indentation[exit 1] -
0b1010 · 0o17 · 0x1f · bin() oct() hex()Three prefixes in, three functions out - and the functions return strings with the prefix included.
bash Example session python3 ~/py/numerals.pyliterals : 10 15 31 10to text : 0b1010 0o17 0x1ffrom text: 10 15 255 -
017Python 2 octal. A leading zero on a multi-digit integer is a SyntaxError in Python 3, not 15 and not 17.
bash Example session python3 -c 'print(017)' File "<string>", line 1 print(017) ^SyntaxError: leading zeros in decimal integer literals are not permitted; use an 0o prefix for octal integers[exit 1] -
True + Truebool is a subclass of int, so this is 2. `True == 1` is True and `True is 1` is False.
bash Example session python3 ~/py/boolint.py/home/sysadmin/py/boolint.py:4: SyntaxWarning: "is" with 'int' literal. Did you mean "=="? print(True == 1, True is 1)2True1 0True False -
/ vs // vs %`/` always returns a float. `//` floors, so -7 // 2 is -4. `%` takes the sign of the right operand.
The single most asked arithmetic question in either exam.
bash Example session python3 ~/py/divs.py4 / 2 = 2.0 float4 // 2 = 2 int4.0 // 2= 2.0 float-7 // 2 = -47 % 3 = 1 -7 % 3 = 2 7 % -3 = -27.5 % 2 = 1.5divmod(7, 2) = (3, 1) -
2 ** 3 ** 2 · -2 ** 2`**` is right-associative and binds tighter than unary minus: 512, and -4.
bash Example session python3 ~/py/power.py2 ** 3 ** 2 = 512(2 ** 3) ** 2 = 64-2 ** 2 = -4(-2) ** 2 = 42 ** -1 = 0.5 -
and / or return an operandNot a boolean. `0 or "x"` is the string, and `0 and 1/0` never divides - short-circuiting is observable.
bash Example session python3 ~/py/logic.pyfallbackb0True True False -
~5 · << >>`~n` is `-n - 1`, so ~5 is -6. Shifts multiply and floor-divide by powers of 2.
bash Example session python3 ~/py/bits.pya & b = 0b1000a | b = 0b1110a ^ b = 0b110~5 = -65 << 2= 20 20 >> 2 = 5 -
round() vs int()round() is nearest-with-ties-to-even, so round(2.5) is 2. int() truncates. round(2.675, 2) is 2.67 for a different reason entirely.
bash Example session python3 ~/py/rounding.pyround(2.5) = 2round(3.5) = 4round(-2.5) = -2round(2.675, 2) = 2.67int(2.9) = 2 -
bool() on everythingZero, empty and None are false. `'0'`, `' '` and `[0]` are all true.
bash Example session python3 ~/py/truthy.py0 -> False1 -> True-1 -> True0.0 -> False'' -> False'0' -> True' ' -> True[] -> False[0] -> True() -> False{} -> FalseNone -> False -
int("3.5")ValueError. int() parses sign and digits only - int(float("3.5")) is the two-step fix.
bash Example session python3 -c 'print(int("3.5"))'Traceback (most recent call last): File "<string>", line 1, in <module> print(int("3.5")) ~~~^^^^^^^ValueError: invalid literal for int() with base 10: '3.5'[exit 1] -
print(*values, sep=" ", end="\n")One space between arguments by default. `sep` goes between, `end` goes after.
bash Example session python3 ~/py/printargs.pya b ca-bxy1 2.0 True None that blank line was an argument-less print -
input() returns strSo `input() + input()` concatenates. Convert at the read: `int(input())`.
The most reliably examined question in objective 1.5.
bash Example session printf '2\n3\n' | python3 ~/py/addtrap.pyfirst : second: a + b = 23int(a) + int(b) = 5
Block 2: Control flow (29%)
-
elif orderTested top to bottom, first true one wins. A broad condition above a narrow one makes the narrow one dead code, with no warning.
bash Example session python3 ~/py/elifordering.pypositivepositivezero or negative -
A if cond else BThe conditional expression. Result first, then the condition - and the else is mandatory.
bash Example session python3 ~/py/ternary.pybigoddbig -
range(stop) · range(start, stop) · range(start, stop, step)Stop is excluded. A negative step counts down. An impossible range is empty, not an error. And a range prints as `range(0, 5)`, not a list.
bash Example session python3 ~/py/ranges.pyrange(5) [0, 1, 2, 3, 4]range(2, 5) [2, 3, 4]range(2, 11, 3) [2, 5, 8]range(5, 0, -1) [5, 4, 3, 2, 1]range(5, 0) []range(0) []range(5) itself range(0, 5) range len 5 -
range(1.5)TypeError - range takes integers only. A zero step is a ValueError instead.
bash Example session python3 -c 'print(list(range(1.5)))'Traceback (most recent call last): File "<string>", line 1, in <module> print(list(range(1.5))) ~~~~~^^^^^TypeError: 'float' object cannot be interpreted as an integer[exit 1] -
the loop variable after the loopA `for` leaves it at the last value; a loop that never ran leaves it unbound and a NameError. A `while` counter overshoots by one.
bash Example session python3 ~/py/loopvar.pyi is still 2Traceback (most recent call last): File "/home/sysadmin/py/loopvar.py", line 7, in <module> print("j is", j) ^NameError: name 'j' is not defined[exit 1] -
for ... elseThe else runs **unless** a break happened. Read it as `nobreak:`.
bash Example session python3 ~/py/loopelse.pybody 0body 1body 2for-else ran because no break happenedbreakingafter -
else after zero iterationsStill runs. No break happened, because there was no opportunity for one.
bash Example session python3 ~/py/elseempty.pyelse ran after zero iterationswhile-else ran after zero iterations -
break in nested loopsLeaves the inner loop only. There is no labelled break and no `break 2`.
bash Example session python3 ~/py/nestedbreak.pyinner 0 0outer iteration 0 continuedinner 1 0outer iteration 1 continuedinner 2 0outer iteration 2 continued
Block 3: Data collections (25%)
-
xs[start:stop:step]Start included, stop excluded. `xs[:]` copies, `xs[::-1]` reverses, `xs[::2]` takes every second.
bash Example session python3 ~/py/slicing.pyxs[1:4] [1, 2, 3]xs[:3] [0, 1, 2]xs[3:] [3, 4, 5]xs[:] [0, 1, 2, 3, 4, 5]xs[::2] [0, 2, 4]xs[1:4:2] [1, 3]xs[::-1] [5, 4, 3, 2, 1, 0]xs[-2:] [4, 5]xs[:-2] [0, 1, 2, 3] -
a slice never raisesOut-of-range slices clamp to what exists. Only single-element indexing raises IndexError.
bash Example session python3 ~/py/sliceedges.pyxs[4:1] []xs[10:20] []xs[2:99] [2, 3, 4, 5] -
xs.sort() vs sorted(xs)The method sorts in place and returns None; the function returns a new list. `xs = xs.sort()` destroys the list.
If you remember one row on this sheet, this one.
bash Example session python3 ~/py/sorting.pysorted([3, 1, 2]) [1, 2, 3][3, 1, 2].sort() returns Noneys.sort() returns None and ys is now [1, 2, 3]after sort(reverse=True) [3, 2, 1]after reverse() [1, 2, 3] -
b = a vs c = a[:]Assignment binds a second name to one list. Slicing copies. Check with `a is b`.
bash Example session python3 ~/py/aliasing.pya [1, 2, 3, 4]b [1, 2, 3, 4]a is b Truea [1, 2, 3, 4]c [1, 2, 3, 4, 5]a is c False -
[[0] * 2] * 3Three names for one inner list. Use a comprehension: `[[0] * 2 for _ in range(3)]`.
bash Example session python3 ~/py/gridtrap.pygrid built with * : [[9, 0], [9, 0], [9, 0]]grid built with a comprehension: [[9, 0], [0, 0], [0, 0]] -
(1) vs (1,)The comma makes the tuple, not the brackets. `(1)` is an int. `()` is the one exception.
bash Example session python3 ~/py/tuplecomma.py(1) is a int(1,) is a tuple() is a tuple1, is a tuple -> (1,)tuple('abc') ('a', 'b', 'c')tuple([1, 2]) (1, 2) -
tuple refusalsAttributeError for `append` (the method does not exist), TypeError for item assignment and deletion.
bash Example session python3 -c 't = (1, 2); t.append(3)'Traceback (most recent call last): File "<string>", line 1, in <module> t = (1, 2); t.append(3) ^^^^^^^^AttributeError: 'tuple' object has no attribute 'append'[exit 1] -
in tests keys, not values`99 in d` is False even when 99 is a value. Use `99 in d.values()`.
bash Example session python3 ~/py/dictbasics.pyd {'a': 1, 'b': 2}len 2d["a"] 1after adding c {'a': 1, 'b': 2, 'c': 3}after reassigning {'a': 99, 'b': 2, 'c': 3}after del b {'a': 99, 'c': 3}"a" in d True99 in d False -
insertion order · duplicate keysOrder is guaranteed since 3.7. And `{1: "int", 1.0: "float", True: "bool"}` is ONE entry, keyed 1, valued "bool".
bash Example session python3 ~/py/dictorder.pyinsertion order kept: ['z', 'a', 'm']{"a": 1, "a": 2} -> {'a': 2}{1: "int", 1.0: "float", True: "bool"} -> {1: 'bool'} -
d["missing"]KeyError. `d.get("missing")` returns None instead, and takes a default.
bash Example session python3 -c 'print({"a": 1}["z"])'Traceback (most recent call last): File "<string>", line 1, in <module> print({"a": 1}["z"]) ~~~~~~~~^^^^^KeyError: 'z'[exit 1] -
split() vs split(" ")No argument collapses runs of whitespace; an explicit separator does not. Same input, three items against four.
bash Example session python3 ~/py/strsplit.py"a b c".split() ['a', 'b', 'c']"a b c".split(" ") ['a', 'b', '', 'c']"a,b,,c".split(",") ['a', 'b', '', 'c']"".split(",") ['']"-".join(["a","b","c"]) a-b-c"".join(["a","b"]) ab -
s += "d" on a stringBuilds a new string and rebinds the name. Any other name still sees the old value - the opposite of a list.
bash Example session python3 ~/py/strrebind.pys: abcdt: abc
Block 4: Functions and exceptions (28%)
-
a function with no returnReturns None. `print(f())` where f only prints produces two lines.
bash Example session python3 ~/py/funcbasics.pythe function object : functionhellocalling it returns : Noneadd(1, 2) : 3nothing() returns : None -
def f(x, target=[])The default is created once, when the def runs. Every call without an argument shares it. `__defaults__` holds the accumulating object.
Asked on both exams, in at least three disguises.
bash Example session python3 ~/py/mutabledefault.py[1][1, 2][1, 2, 3]the default itself: ([1, 2, 3],) -
def f(a, b=1, c)SyntaxError - compile time, so the program prints nothing at all.
bash Example session python3 ~/py/baddef.py File "/home/sysadmin/py/baddef.py", line 4 def f(a, b=1, c): ^SyntaxError: parameter without a default follows parameter with a default[exit 1] -
rebind vs mutateA function cannot rebind the caller's name and can mutate the caller's object. That single distinction answers most argument questions.
bash Example session python3 ~/py/passing.pyinside rebind, x is 99after rebind, n is 1inside mutate, xs is [1, 99]after mutate, ys is [1, 99] -
UnboundLocalErrorAn assignment anywhere in a function makes the name local everywhere in it - including the line above that reads it.
bash Example session python3 ~/py/unbound.pyTraceback (most recent call last): File "/home/sysadmin/py/unbound.py", line 9, in <module> broken() ~~~~~~^^ File "/home/sysadmin/py/unbound.py", line 5, in broken print(x) ^UnboundLocalError: cannot access local variable 'x' where it is not associated with a value[exit 1] -
LEGBLocal, Enclosing, Global, Built-in. First match wins and the search stops.
bash Example session python3 ~/py/legb.pyinner sees enclosingand len() comes from the builtin scope: 3 -
no base caseRecursionError - a subclass of RuntimeError - at a default depth of 1000. Not StackOverflowError, which is another language.
bash Example session python3 ~/py/norecursionbase.pythe limit is 1000Traceback (most recent call last): File "/home/sysadmin/py/norecursionbase.py", line 10, in <module> forever(0) ~~~~~~~^^^ File "/home/sysadmin/py/norecursionbase.py", line 7, in forever return forever(n + 1) File "/home/sysadmin/py/norecursionbase.py", line 7, in forever return forever(n + 1) File "/home/sysadmin/py/norecursionbase.py", line 7, in forever return forever(n + 1) [Previous line repeated 996 more times]RecursionError: maximum recursion depth exceeded[exit 1] -
the exception hierarchyPrinted from __bases__. The three nobody guesses: TabError under IndentationError under SyntaxError, UnboundLocalError under NameError, RecursionError under RuntimeError.
bash Example session python3 ~/py/hierarchy.pyZeroDivisionError <- ArithmeticError <- Exception <- BaseExceptionOverflowError <- ArithmeticError <- Exception <- BaseExceptionArithmeticError <- Exception <- BaseExceptionIndexError <- LookupError <- Exception <- BaseExceptionKeyError <- LookupError <- Exception <- BaseExceptionLookupError <- Exception <- BaseExceptionValueError <- Exception <- BaseExceptionTypeError <- Exception <- BaseExceptionAttributeError <- Exception <- BaseExceptionNameError <- Exception <- BaseExceptionUnboundLocalError <- NameError <- Exception <- BaseExceptionImportError <- Exception <- BaseExceptionModuleNotFoundError <- ImportError <- Exception <- BaseExceptionOSError <- Exception <- BaseExceptionFileNotFoundError <- OSError <- Exception <- BaseExceptionEOFError <- Exception <- BaseExceptionStopIteration <- Exception <- BaseExceptionAssertionError <- Exception <- BaseExceptionMemoryError <- Exception <- BaseExceptionRecursionError <- RuntimeError <- Exception <- BaseExceptionSyntaxError <- Exception <- BaseExceptionIndentationError <- SyntaxError <- Exception <- BaseExceptionTabError <- IndentationError <- SyntaxError <- Exception <- BaseExceptionException <- BaseExceptionKeyboardInterrupt <- BaseExceptionSystemExit <- BaseException -
BaseException.__subclasses__()KeyboardInterrupt and SystemExit sit outside Exception, which is why `except Exception:` does not catch Ctrl-C.
bash Example session python3 -c 'print([c.__name__ for c in BaseException.__subclasses__()])'['BaseExceptionGroup', 'Exception', 'GeneratorExit', 'KeyboardInterrupt', 'SystemExit'] -
except clause orderSpecific before general. A base class above its subclass makes the subclass clause unreachable, silently.
bash Example session python3 ~/py/badorder.pythe general clause caught it first -
except (A, B) · else · finallyA tuple of types in one clause. `else` runs only on success; `finally` runs always, including after zero iterations of anything.
bash Example session python3 ~/py/multitype.py'5' converted to 5'5' - finally always runs'x' failed with ValueError'x' - finally always runsNone failed with TypeErrorNone - finally always runs
The one-liners worth knowing cold
-
-7 // 2 · -7 % 2 · 2 ** 3 ** 2 · -2 ** 2-4, 1, 512, -4. Four separate questions in one line.
bash Example session python3 -c 'print(-7 // 2, -7 % 2, 2 ** 3 ** 2, -2 ** 2)'-4 1 512 -4 -
"abcdef"[::-2] · [4:1] · len("a\tb")fdb, an empty string, 3. An escape is one character.
bash Example session python3 -c 'print("abcdef"[::-2], "abcdef"[4:1], len("a\tb"))'fdb 3 -
bool("0") · bool([0]) · int(-3.9) · round(2.5)True, True, -3, 2.
bash Example session python3 -c 'print(bool("0"), bool([]), bool([0]), int(-3.9), round(2.5))'True False True -3 2
No command matches that search.