AI Skill Report Card

Using Python Built In Constants

B+78·Aug 12, 2026·Source: Web
13 / 15
Python
# Correct usage patterns for Python built-in constants # None: absence of a value, always compare with `is` def find_user(id): result = None return result if result is None: print("not found") # True/False: instances of bool, subclass of int assert True == 1 and False == 0 assert isinstance(True, int) # NotImplemented: returned from special methods, not raised class Vector: def __eq__(self, other): if not isinstance(other, Vector): return NotImplemented return self.x == other.x # Ellipsis (...): placeholder in slicing, stubs, type hints def stub_function() -> int: ... matrix[..., 0] # slice shorthand for multi-dim arrays # __debug__: True unless run with -O flag if __debug__: print("debug mode checks run") assert some_condition # skipped entirely when -O is used # Site-module constants (interactive shell only, not for scripts) # quit, exit, copyright, credits, license
Recommendation
Add a 'bad output' example showing incorrect usage side-by-side with the fix (e.g., `== None` vs `is None`) to strengthen the examples section per best practices.
13 / 15

Progress:

  • Identify which constant fits the semantic need (null vs boolean vs unimplemented vs placeholder)
  • Use correct comparison idiom (is/is not for None, NotImplemented)
  • Never use site-module constants (quit, exit, copyright, etc.) in production code
  • Use __debug__ for development-only assertions, not for security or business logic
  • Return NotImplemented (don't raise it) inside dunder methods when operation isn't supported

Step 1: Distinguish the six core constants

ConstantTypePurposeComparison
True/FalseboolBoolean truth values==, is both work (singletons)
NoneNoneType"No value" / nullAlways is None / is not None
NotImplementedNotImplementedTypeSignal unsupported operation in rich comparisons/arithmetic dundersReturn it, don't raise; don't use in boolean context
Ellipsis (...)EllipsisTypePlaceholder — slicing, stub bodies, type hintsRarely compared; used as syntax ...
__debug__boolTrue normally, False with -O/-OOUse in if __debug__: guards

Step 2: Apply idiomatic patterns

None checks:

Python
if value is None: # correct if value == None: # avoid — triggers __eq__, can misbehave

NotImplemented in operator overloading:

Python
def __lt__(self, other): if not isinstance(other, MyClass): return NotImplemented # let Python try other.__gt__ or raise TypeError return self.value < other.value

Never do if x == NotImplemented or use it as a boolean — treat it strictly as a return sentinel.

Ellipsis for stubs and slicing:

Python
def not_yet_implemented(): ... # numpy-style slicing arr[..., 0] # equivalent to arr[:, :, 0] for 3D array

debug for assert-guarded code:

Python
if __debug__: _validate_invariants() # stripped out entirely under python -O

Never rely on __debug__/assert for security checks — they vanish under -O.

Step 3: Handle site-module constants correctly

quit, exit, copyright, credits, license are added by the site module only in interactive interpreter sessions. They:

  • Are NOT guaranteed to exist in scripts, embedded interpreters, or when run with -S
  • Should never be used programmatically (e.g., exit() in a script) — use sys.exit() instead
  • Exist purely for human convenience at the REPL
Python
# Bad: script relying on interactive-only builtins exit() # may not exist if site module wasn't imported # Good: import sys sys.exit(0)
Recommendation
The topic is somewhat niche/low-stakes for a dedicated skill—consider whether this content could be more impactful merged into a broader 'python idioms' skill or trimmed further given its narrow real-world necessity.
16 / 20

Example 1: Input: Function should return None when no match is found, and caller needs to check. Output:

Python
def find(items, target): for item in items: if item == target: return item return None result = find([1, 2, 3], 5) if result is None: print("Not found")

Example 2: Input: Implement __eq__ for a custom class that should support comparison only with same type. Output:

Python
class Point: def __init__(self, x, y): self.x, self.y = x, y def __eq__(self, other): if not isinstance(other, Point): return NotImplemented return self.x == other.x and self.y == other.y

Example 3: Input: Write a type stub file (.pyi) function signature with no body. Output:

Python
def process(data: list[int]) -> dict[str, int]: ...

Example 4: Input: Code has assert isinstance(x, int) used to validate untrusted user input for a security check. Output: Flag as pitfall — replace with explicit runtime check:

Python
if not isinstance(x, int): raise TypeError("x must be int")

Reason: assert and reliance on __debug__ are removed with -O, so security-critical validation must never depend on them.

Recommendation
Tighten the Best Practices and Common Pitfalls sections, which overlap significantly with the Workflow steps—consolidate redundant NotImplemented/None/__debug__ guidance to reduce repetition and shorten the file.
  • Always use is/is not for None and NotImplemented — they are singletons; identity comparison is faster and avoids operator overload surprises.
  • Return NotImplemented, never raise it — raising breaks Python's reflected-operation fallback mechanism (__radd__, __req__, etc.).
  • Use Ellipsis/... for stub bodies instead of pass when signaling "unimplemented but intentional" (helps distinguish from placeholder pass).
  • Gate expensive diagnostic code with if __debug__: to let -O optimize it away in production.
  • Prefer sys.exit() over the site-added exit()/quit() in any script or module.
  • Remember bool is a subclass of int: True + True == 2 is valid but should be avoided for readability — don't rely on this arithmetic behavior in serious code.
  • Comparing with == instead of is for None/NotImplemented — can trigger unexpected __eq__ behavior or return ambiguous truthy/falsy results.
  • Using NotImplemented in a boolean context (e.g., if not_implemented_value:) — it's truthy, so if x: doesn't tell you whether an operation failed; always check is NotImplemented explicitly if needed.
  • Confusing NotImplemented with NotImplementedError — the former is a value returned from dunder methods; the latter is an exception raised in abstract methods. They are not interchangeable.
  • Relying on assert/__debug__ for input validation or security — stripped under python -O, creating silent security holes.
  • Using quit(), exit(), copyright, credits, license in production scripts — only guaranteed in interactive sessions; absent when site isn't imported (e.g., -S flag, embedded interpreters, some frozen apps).
  • Overusing Ellipsis outside stubs/slicing — using ... as a generic "TODO" placeholder in real logic paths can silently pass type checks while doing nothing at runtime.
0
Grade B+AI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
13/15
Workflow
13/15
Examples
16/20
Completeness
18/20
Format
14/15
Conciseness
12/15