CertGrid CertGrid

PCAP cheat sheet

What PCAP-31-03 adds to PCEP, grouped by its five sections - modules, exceptions, strings, object-oriented programming and the miscellaneous 22%. Weighted the way the exam is: OOP gets the most rows because it is 34% of the paper.

Section 1: Modules and packages (12%)

  • import · import as · from import · from import as · from import *

    Five forms, five different sets of names bound. That difference is the whole objective.

    Full guide
  • from math import pi, then math.pi

    NameError - not ImportError. The import succeeded; the name `math` was never bound.

    Full guide
  • a missing module vs a missing name

    ModuleNotFoundError for the module, ImportError for a name inside one. The first is a subclass of the second.

    Full guide
  • a module body runs once

    Three import statements, one execution. Python caches it in sys.modules.

    Full guide
  • __name__ == "__main__"

    `"__main__"` when run directly, the module name when imported.

    Full guide
  • ceil · floor · trunc · round

    Four directions, and they disagree on negatives. floor(-2.9) is -3; trunc(-2.9) is -2.

    Full guide
  • math.pow vs **

    math.pow always returns a float; `**` on two ints returns an int. Almost everything in math returns a float.

    Full guide
  • sin() takes radians

    So sin(90) is not 1. `math.radians(90)` first.

    Full guide
  • random.seed(n)

    The same seed gives the same sequence, every run. Which is why every random example in this path is seeded.

    Full guide
  • randint vs randrange

    randint(1, 3) can return 3. randrange(1, 3) cannot - it follows range semantics.

    Full guide
  • shuffle vs sample

    shuffle reorders in place and returns None; sample returns a new list. `sample(xs, len(xs))` is a shuffled copy.

    Full guide
  • platform.system() · machine() · node()

    OS name, architecture, hostname. system() returns "Darwin" on macOS. processor() is often an empty string.

    Full guide
  • import pkg does not import pkg.mod

    AttributeError. Use `import pkg.mod`, or `from . import mod` inside __init__.py.

    The most asked question in objective 1.5.

    Full guide

Section 2: Exceptions (14%)

  • a bare raise

    Re-raises the exception currently being handled, keeping its original traceback. Outside a handler it is a RuntimeError.

    Full guide
  • assert (cond, "msg")

    Always passes. The brackets make a two-item tuple, which is truthy. Write `assert cond, "msg"`.

    Full guide
  • python3 -O

    Removes every assertion from the compiled code. Never use assert to validate input.

    Full guide
  • return inside finally

    Discards the exception entirely - no handler, no traceback. Python 3.14 warns; the behaviour is unchanged and examinable.

    Full guide
  • e.args and str(e)

    One argument gives that string. Several give the repr of the whole tuple. None gives an empty string.

    Full guide
  • except ... as e

    The name is deleted when the clause ends, to release the traceback. Copy it inside the block if you need it after.

    Full guide
  • a family of exceptions

    One base class, several subclasses, and `except AppError:` catches all of them. That is what objective 2.2 is for.

    Full guide
  • raising a non-exception

    TypeError: exceptions must derive from BaseException - at run time, not at class definition.

    Full guide

Section 3: Strings (18%)

  • s.encode() / b.decode()

    "café" is 4 characters and 5 UTF-8 bytes. There is no str.decode() in Python 3.

    Full guide
  • the same bytes, two encodings

    UTF-8 bytes read as latin-1 give `café`. No error - latin-1 can decode any byte.

    Full guide
  • b[0] vs b[0:1]

    Indexing bytes gives an int; slicing gives bytes. And bytes never mix with str.

    Full guide
  • ord() and chr()

    Space 32, '0' 48, 'A' 65, 'a' 97. Those four numbers derive everything else.

    Full guide
  • the gap between Z and a

    Six punctuation characters. Which is why "Z" < "a" and why sorting mixed case needs a key.

    Full guide
  • a caesar shift

    Subtract ord("a"), add the shift, `% 26`, add ord("a") back. The `% 26` is what makes it wrap.

    Full guide
  • the 24 methods PCAP names

    All of them in one run: case, trim, search, split/join, and the six is-methods.

    Full guide
  • the optional arguments

    count and find take a start; replace takes a maximum; endswith takes a tuple; strip("x") strips characters, not a substring.

    Full guide
  • capitalize vs title

    Both lowercase the rest. title() treats an apostrophe as a word boundary, so o'brien becomes O'Brien.

    Full guide

Section 4: Object-oriented programming (34%)

  • __str__ vs __repr__

    print() uses __str__; a list of your objects uses __repr__. Define __repr__ if you only define one.

    Full guide
  • __init__ returning a value

    TypeError: __init__() should return None. A bare `return` is fine.

    Full guide
  • def __init__(self, items=[])

    Every instance shares one list. `items=None` and build it inside.

    Full guide
  • self in the argument count

    "takes 1 but 2 were given" counts self. "missing 1 required" does not. Both messages are correct.

    Full guide
  • obj.m vs Class.m

    A bound method against a plain function. `Class.m(obj)` is exactly `obj.m()`.

    Full guide
  • a.total = 100 on a class variable

    Creates an instance variable that shadows it. The class variable is unchanged. Reading searches instance then class; writing always hits the instance.

    The one rule the whole 34% section turns on.

    Full guide
  • a mutable class variable

    Shared by every instance, and `a.__dict__` is empty - which is the proof. append is a read followed by a mutation, not an assignment.

    Full guide
  • self.made += 1

    Reads from the class, writes to the instance. Every instance says 1 and the class stays 0. Use `ClassName.made += 1`.

    Full guide
  • self.__private

    Renamed to `_ClassName__private` at compile time. Not private - reachable by anyone who knows the rule.

    Full guide
  • why mangling exists

    Collision avoidance, not privacy. A base and a subclass can each keep their own `self.__x`.

    Full guide
  • __class__ · __name__ · __bases__ · __mro__

    __bases__ is the direct parents; __mro__ is the full lookup order, ending at object. Both are tuples.

    Full guide
  • __doc__ is not inherited

    A subclass with no docstring of its own has None, not the parent's. Every other class attribute does fall through.

    Full guide
  • isinstance vs type() is

    isinstance accepts subclasses; `type(x) is C` demands an exact match. Use isinstance.

    Full guide
  • a subclass __init__ without super()

    Constructs happily, missing an attribute, and fails somewhere else later. `super().__init__(...)` first.

    Full guide
  • super().method()

    The next class along the MRO - one step, not to the root.

    Full guide
  • the diamond

    D(B, C) with only C defining the method resolves to C, not A - because A comes after both in the MRO.

    Full guide
  • super() in a diamond

    B's super() goes to C, its sibling - not to A, its base. super() follows the instance's MRO.

    Full guide
  • class C(A, B) after class B(A)

    TypeError: cannot create a consistent MRO - at class-creation time. List the most derived base first.

    Full guide

Section 5: Comprehensions, lambdas, closures, I/O (22%)

  • [expr for x in xs if cond]

    A trailing `if` filters; an `if`/`else` in the expression transforms. Count the outputs to tell which.

    Full guide
  • the brackets decide the type

    Square gives a list, `{k: v}` a dict, `{v}` a set, round a **generator** - not a tuple.

    Full guide
  • the comprehension variable

    Does not leak - NameError afterwards. A plain `for` loop does leave it bound.

    Full guide
  • map(f, xs)

    Returns a lazy iterator in Python 3, not a list. Several iterables stop at the shortest.

    Full guide
  • filter(None, xs)

    Keeps the truthy items. On the syllabus and almost never taught.

    Full guide
  • reduce

    NameError - it lives in functools in Python 3, not the built-ins.

    Full guide
  • [lambda: i for i in range(3)]

    All three return 2. They closed over the variable, not its value. `lambda i=i: i` fixes it.

    One of the hardest questions in section 5.

    Full guide
  • f.__closure__

    None for a plain function; a tuple of cells for a closure. `co_freevars` names what was captured.

    Full guide
  • r · w · a · r+ · w+ · a+ · b

    w truncates on open, before you write anything. a always writes at the end. r is the default.

    Full guide
  • with open(...) as f

    Closes on every path out, including when an exception propagates through.

    Full guide
  • the file position

    A second read() returns an empty string - the position is at the end. f.seek(0) rewinds.

    Full guide
  • readlines() keeps the newlines

    And the last line has none if the file does not end with one - `['a\n', 'b']`.

    Full guide
  • bytearray

    A mutable bytes. Assign a number, not a character. `bytearray(3)` is three zero bytes.

    Full guide
  • f.readinto(buffer)

    Fills a bytearray you already own and returns the count. Needs a mutable buffer.

    Full guide