Exercise Answers¶
Page Maps¶
graph LR
family["Python Programming"]
program["Python Meta-Programming"]
section["Runtime Objects Object Model"]
page["Exercise Answers"]
capstone["Capstone evidence"]
family --> program --> section --> page
page -.applies in.-> capstone
flowchart LR
orient["Orient on the page map"] --> read["Read the main claim and examples"]
read --> inspect["Inspect the related code, proof, or capstone surface"]
inspect --> verify["Run or review the verification path"]
verify --> apply["Apply the idea back to the module and capstone"]
Use this page after you have attempted the exercises yourself. The point is not to match every example literally. The point is to compare your reasoning against an answer that names the runtime object, cites evidence, and stays honest about boundaries.
Answer 1: Tell the truth about one function object¶
Example answer:
Strong evidence:
fn.__name__ == "inner"fn.__qualname__includes"outer.<locals>.inner"fn.__module__names the defining modulefn.__code__.co_freevars == ("base",)fn.__closure__exists because the function captures an outer binding
Good conclusion:
fn is more than "something callable." It is a Python-defined function object carrying
identity, metadata, executable code, and closure state.
Answer 2: Explain one class without saying "class magic"¶
Example answer:
Strong evidence:
type(Demo) is typeDemo.__bases__shows the direct basesDemo.__dict__["run"] is Demo.runDemo()creates an instance whose__class__isDemo
Good conclusion:
The class statement created a class object, stored a function object under run, and
instance access later binds that function into a method. No special "magic" explanation
is required.
If you used a descriptor example, a strong answer also says whether a data descriptor, instance storage, or non-data descriptor won the lookup.
Answer 3: Prove module identity and stale imported values¶
Example answer:
import importlib
import sys
import types
name = "sample_mod"
mod = types.ModuleType(name)
mod.value = "old"
sys.modules[name] = mod
again = importlib.import_module(name)
copied = mod.value
mod.value = "new"
Strong evidence:
mod is againproves both names refer to the same module objectmod.value == "new"whilecopied == "old"proves copied-out values can go stale
Good conclusion:
Imports usually return references to a cached module object. Names copied out of the module do not automatically refresh when the module namespace changes.
Answer 4: Compare instance storage models honestly¶
Example answer:
class Regular:
pass
class Slotted:
__slots__ = ("x",)
regular = Regular()
regular.x = 1
slotted = Slotted()
slotted.x = 1
Strong evidence:
regular.__dict__ == {"x": 1}hasattr(slotted, "__dict__")is oftenFalse- assigning
slotted.y = 2raisesAttributeError
Good conclusion:
The regular instance stores dynamic state in a dictionary. The slotted instance uses a
fixed storage layout and rejects undeclared attributes. __slots__ is justified when the
layout is stable and the memory or constraint tradeoff is intentional, not when it is
added only to make the code look advanced.
Answer 5: Trace one runtime object chain from module to call¶
Example answer:
class Processor:
def process(self, data):
return len(data)
import sys
module = sys.modules[__name__]
cls = module.Processor
inst = cls()
bound = inst.process
func = bound.__func__
Strong evidence:
cls is module.Processorinst.__class__ is clsbound.__self__ is instbound.__func__ is cls.processfunc.__globals__ is module.__dict__
Good conclusion by runtime moment:
- import time: the module object was created and executed
- class-definition time: the class object was built and bound into the module namespace
- instance-creation time: calling the class created
inst - call time: instance lookup created
bound, and calling it invokedfuncwith access to module globals
This trace prevents several misunderstandings at once, especially the idea that methods are stored inside instances or that call behavior can be explained without reference to the module and class objects involved.
Answer 6: Review a brittle introspection helper¶
Example answer:
Suppose the helper tries to recover source with:
func.__code__.co_filenamefunc.__code__.co_firstlineno- indentation scanning
Strong classification:
__name__,__qualname__, andinspect.signature()are supported introspection surfaces__code__,co_filename, andco_firstlinenoare diagnostic surfaces useful for tools but too weak for guaranteed source recovery- indentation scanning is a heuristic layered on top of incomplete runtime metadata
Good conclusion:
The rewrite should report supported metadata first and use inspect.getsource(func) only
as a best-effort convenience with a clear failure path. The tool should not claim that it
can reconstruct the true source of any callable from code-object fields alone.
What strong Module 01 answers have in common¶
Across the whole set, strong answers share the same habits:
- they start from a named runtime object
- they use evidence instead of folklore
- they distinguish supported surfaces from implementation detail
- they explain behavior in terms of import time, class-definition time, instance time, and call time when relevant
If your answer still depends on phrases like "Python just knows" or "class magic," revise it until you can point to the actual object and relationship doing the work.