Python's Hidden Depths

There is a function in the codebase that Priya has been afraid of for months. It sits at the top of the API layer, five lines long, and every route handler is wrapped in it. It starts with `@require_auth` and somehow — through a mechanism she cannot trace — it checks whether a user is logged in before the actual function runs. She knows it is a decorator because her tech lead said so. She has no idea how a function can wrap another function, where the original function goes, or why there are two nested `def` statements inside it. She has avoided decorators the way people avoid highway merges in an unfamiliar city: by taking side streets. She writes the validation logic inline, repeating herself across handlers, because at least she understands what the code is doing. Her tech lead left a PR comment last week that said "this would be a good candidate for a decorator" and she responded with a thumbs-up emoji and changed nothing. The secret nobody tells junior developers is that decorators are not a language feature. They are a consequence of two simpler ideas: functions can return other functions, and a function can remember the variables that existed when it was created. The `@` symbol is just syntax sugar. Once Priya understands what happens when a function is born inside another function and carries its parent's variables with it, `@require_auth` will read like a sentence instead of a spell.