# Python absence — decide "missing" where the value is born — worked examples

One bad → good per rule this skill teaches, taken from the fixture that proves the detector, so every pair is code that really fires and really passes.

### python-blank-string-default

`x: str = ""` standing in for absence — then asked `x == ""`, `not x` or `if x:` in its own scope

```py
----------[ Bad ]----------

def book(self, parcel: str, tracking: str = "") -> str:
    if not tracking:
        tracking = self.api.issue(parcel)
    return self.api.book(parcel, tracking)

----------[ Good ]----------

def book_tracked(self, parcel: str, tracking: str | None = None) -> str:
    if tracking is None:
        tracking = self.api.issue(parcel)
    return self.api.book(parcel, tracking)
```

### python-cancelled-fallback

`(x or "") != ""` — a value defaulted to a blank only to be compared against that same blank, so a missing value and an empty one are treated the same without saying so.

```py
----------[ Bad ]----------

def stock_rows(rows: list, stock) -> None:
    for row in rows:
        if row.get("qty", 0) == 0:
            continue
        stock.add(row["sku"], row["qty"])

----------[ Good ]----------

def stock_counted(rows: list, stock) -> None:
    for row in rows:
        if "qty" not in row:
            raise MissingQuantity.in_row(row)
        if row["qty"] == 0:
            continue
        stock.add(row["sku"], row["qty"])
```

### python-conditional-spread

`**({"k": v} if v else {})` / `*([x] if x else [])` — an entry is spread in only when present, using a conditional that turns absence into an empty collection.

```py
----------[ Bad ]----------

def notify(transport, to: str, body: str, cc: str | None = None) -> None:
    transport.send(to, body, **({"cc": cc} if cc else {}))

----------[ Good ]----------

def notify_all(transport, to: str, body: str, cc: str | None = None) -> None:
    transport.send(to, body, cc=cc)
```

### python-invented-default

`f(x or "")` — an empty string, `0` or `False` invented to fill an argument when the value is missing, a stand-in the callee cannot tell from real data

```py
----------[ Bad ]----------

def send_receipt(order, mailer) -> None:
    mailer.send(order.email or "", subject=f"Receipt {order.number}")

----------[ Good ]----------

# in receipts.py
class NoEmail(LookupError):
    @classmethod
    def on(cls, order) -> "NoEmail":
        return cls(f"order {order.number} has no email to send the receipt to")

# in receipts.py
def mail_receipt(order, mailer) -> None:
    if order.email is None:
        raise NoEmail.on(order)
    mailer.send(order.email, subject=f"Receipt {order.number}")
```

### python-nullable-callback

`cb: Callable | None = None` asked `if cb is not None:` / `if cb:` / `cb or …` in the body — a no-op treated as if it might be missing.

```py
----------[ Bad ]----------

def with_retries(work: Callable[[], bool], attempts: int, on_retry: Callable[[int], None] | None = None) -> bool:
    for attempt in range(attempts):
        if work():
            return True
        if on_retry is not None:
            on_retry(attempt)
    return False

----------[ Good ]----------

def retrying(work: Callable[[], bool], attempts: int, on_retry: Callable[[int], None] = ignore) -> bool:
    for attempt in range(attempts):
        if work():
            return True
        on_retry(attempt)
    return False
```
