Home / software-development / PCAP – Certified Associate Python Programmer (PCAP-31-03) / Cheat Sheet
PCAP – Certified Associate Python Programmer (PCAP-31-03)

PCAP Cheat Sheet

PCAP Tests Exact Output Prediction — Not Whether You Can Write Python

PCAP-31-03 rewards tracing snippets line by line: name binding, lookup order, return types. PCAP-31-04 was scheduled to replace it from 31 October 2026, so confirm which version you book.

Check Your Readiness →
Among the harder certs
Avg: Not published by OpenEDG Python Institute
Pass: 750 / 1000
Most candidates understand PCAP – Certified Associate Python Programmer (PCAP-31-03) concepts — and still fail. This exam tests how you apply knowledge under pressure.

PCAP-31-03 Section Map

Nearly every item is a five-to-fifteen-line snippet: choose what it prints or which line raises. Multiple-select items ask for every valid statement. OOP alone is a third of the score, and distractors are built from habits that look right but differ by one detail such as 4 vs. 4.0.

  1. 01
    Object-Oriented Programming (34%) — class vs. instance variables, MRO, name mangling, super(), introspection
  2. 02
    Miscellaneous (22%) — comprehensions, lambda with map/filter, closures, nonlocal, file modes and errno
  3. 03
    Strings (18%) — code points, slicing, immutability, find vs. index, split/join/strip edge cases
  4. 04
    Exceptions (14%) — except branch order, else/finally flow, built-in hierarchy, args tuples, custom classes
  5. 05
    Modules and Packages (12%) — import binding, math rounding, random, platform, __name__ and __init__.py

Wrong instinct vs correct approach

Snippet does import math as m, then prints math.pi on the next line
✕ Wrong instinct

It prints 3.141592653589793 because math was imported

✓ Correct approach

The as clause binds only m, so the name math does not exist and the line raises NameError. List the exact names each import form binds before tracing; from-imports likewise never bind the module name.

A function returns lambda x: x * n, and its result feeds map() over filter()
✕ Wrong instinct

print(map(...)) shows the list of computed values

✓ Correct approach

map() and filter() return lazy iterators in Python 3, so printing one shows <map object at ...>. Only list() shows values; with n = 3, list(map(t, filter(lambda y: y > 1, [1, 2, 3]))) gives [6, 9].

A class stores self.__balance and outside code prints obj.__balance
✕ Wrong instinct

It prints the balance because Python has no real privacy

✓ Correct approach

Two leading underscores trigger name mangling to _ClassName__balance, so the plain name raises AttributeError. From outside the class, only the mangled form works, such as obj._Account__balance for a class named Account.

Code prints e.args after raise ValueError('error') inside a try block
✕ Wrong instinct

The output is the string error

✓ Correct approach

args is always a tuple of constructor arguments, so it prints ('error',) with the trailing comma; print(e) shows just error. The name e is deleted when the handler ends, so using it afterwards raises NameError.

Know these cold

  • ▸ floor(-2.5) is -3, trunc(-2.5) is -2, ceil(-2.5) is -2; sqrt(16) is 4.0
  • ▸ find() returns -1 when missing; index() raises ValueError
  • ▸ '10' < '9' is True and 'Z' < 'a' is True — omparison is by code point
  • ▸ Plain split() drops empty strings; split(',') on 'a,,b' keeps them — 'a', '', 'b']
  • ▸ join() needs all strings; '-'.join([1, 2]) raises TypeError
  • ▸ else runs only if try raised nothing; finally runs always, and a return in finally wins
  • ▸ KeyboardInterrupt and SystemExit derive from BaseException, so except Exception misses them
  • ▸ Star import skips underscore names unless __all__ lists them; a repeat import does not rerun code
  • ▸ readlines() keeps each trailing newline; readline() returns '' at end of file
  • ▸ Mode 'w' truncates, 'a' appends, 'x' raises FileExistsError if the file exists

Can you answer these without checking your notes?

In this scenario: "Snippet does import math as m, then prints math.pi on the next line" — what should you do first?
The as clause binds only m, so the name math does not exist and the line raises NameError. List the exact names each import form binds before tracing; from-imports likewise never bind the module name.
In this scenario: "A function returns lambda x: x * n, and its result feeds map() over filter()" — what should you do first?
map() and filter() return lazy iterators in Python 3, so printing one shows <map object at ...>. Only list() shows values; with n = 3, list(map(t, filter(lambda y: y > 1, [1, 2, 3]))) gives [6, 9].
In this scenario: "A class stores self.__balance and outside code prints obj.__balance" — what should you do first?
Two leading underscores trigger name mangling to _ClassName__balance, so the plain name raises AttributeError. From outside the class, only the mangled form works, such as obj._Account__balance for a class named Account.

Common Exam Mistakes — What candidates get wrong

Expecting obj.count += 1 to update a class variable for everyone

Augmented assignment through an instance reads the class value, then writes a new instance attribute. After c.n += 1 on class Cnt with n = 0, Cnt.n is still 0 and c.n is 1. Only Cnt.n += 1 changes the shared value.

Resolving a diamond hierarchy depth-first instead of by C3 MRO

For class D(B, C) where B and C both inherit A, D.__mro__ is D, B, C, A, object, so a method defined in C beats A. Listing a parent before its own subclass, as in class X(A, B) with B(A), raises TypeError.

Putting a parent except branch above its child and expecting the child

Python runs the first matching except, top to bottom. With except ArithmeticError above except ZeroDivisionError, 1 / 0 prints the ArithmeticError branch. else is then skipped, and finally still runs, even after a return in try.

Assuming a default argument list is fresh on every call

Defaults are evaluated once, when def runs. def f(x, L=[]) appends into the same list each call, so f(1) then f(2) returns [1, 2]. The idiom is L=None, then create the list inside the body.

Expecting each lambda in a loop to remember its own value

Closures capture variables, not values, and look them up when called. [lambda: i for i in range(3)] gives three functions returning 2. Binding a default, lambda i=i: i, freezes each value; assigning to an outer name needs nonlocal or raises UnboundLocalError.

Resources to help you pass Python Institute PCAP on your first attempt

PCAP marks exact output, down to 4 versus 4.0. Test your tracing on real gotchas.