Scope and Namespace in Python
Built-in function names like max, len, sum, and print should be treated as reserved words and never used as variable names.
A Familiar Name Can Change Meaning
Python provides dozens of built-in functions without requiring an import. Names such as print, len, max, min, sum, and type are part of everyday Python programming. Python also allows you to create variables with those same names. That flexibility creates a naming trap: assigning a value to one of these names can hide the built-in function in the scope where the assignment exists.
Namespaces and Hidden Built-ins
A namespace is the setting in which a name is associated with something, such as a variable value or a built-in function. The important collision described here is between a name you assign and a built-in name that Python normally makes available. Before an assignment, len refers to the built-in function. After assigning a value to len, the name len refers to your variable in that scope instead. The built-in has not become a good variable name; it has been shadowed, meaning hidden by the newer name.
The central idea is not that Python removes the built-in permanently. The problem is that the built-in becomes inaccessible through that name in the affected scope, so later code that expects the function can fail.
Tracing a Shadowed Name
What do you think happens?
Suppose a program first uses len as the built-in function, then assigns a value to len, and later tries to call len on a collection. What should you expect at the later call?
Reveal answer
Answer: The variable named len hides the built-in, so the call fails.
Assigning the same name as a built-in shadows that built-in in the affected scope. The error appears when the code later tries to call the shadowed name.
The len collision
A programmer uses len as a variable name and later wants to use len as a built-in function.
Initial meaning: Before the assignment, len names the built-in function that is available for everyday Python use.
Assignment: The programmer assigns a value to len. In that scope, the variable now shadows the built-in function.
Later call: When later code tries to call len with a collection, it reaches the variable name rather than the expected built-in function, so the call fails.
Repair: Use a descriptive name such as item_count or collection_length instead of len, then restart the program or use a documented workaround if the built-in has already been shadowed.
The assignment location and the failure location are different: the name collision is created at assignment, but the visible bug appears when the shadowed name is called.
Why the Bug Appears Later
Shadowing is difficult to debug because assigning the conflicting name may not produce an immediate error. The assignment itself is allowed. The problem becomes visible later, when the program tries to use the name as though it still referred to the built-in function. This separates the cause from the symptom: the assignment creates the collision, while a later call exposes it.
Shadowing also makes code harder for other programmers to read. They normally expect max to refer to the familiar built-in function, not to an unrelated value. If the built-in is needed after shadowing has occurred, the source notes that restarting the program or using a workaround such as importing the builtins module may restore access. Avoiding the collision is simpler and clearer.
Names That Protect Intent
Choose a name that describes what the value represents instead of reusing a built-in function name. For example, use max_score rather than max when storing the highest score, or use item_count rather than len when storing a count. Descriptive names both prevent shadowing and make the code's intent clearer.
| Avoid | Prefer | Reason |
|---|---|---|
| max | max_score | The name explains which maximum is stored. |
| len | item_count | The name describes the stored count. |
| sum | total_amount | The name describes the total's meaning. |
| printed_message | The name does not hide the output function. |
Descriptive alternatives reduce collisions with commonly used built-ins.
- Protect frequently used built-in names such as print, len, max, min, sum, type, range, str, int, float, list, dict, set, tuple, open, input, and sorted.
- Pause when a variable name matches a familiar built-in function.
- Replace the collision with a descriptive name that identifies what the variable stores.
- If a built-in has already been shadowed, inspect earlier assignments before diagnosing the later call.
Practice the Naming Decision
Rewrite each proposed variable name so that it does not shadow a built-in and communicates the value's purpose: max for a student's highest score, len for the number of selected items, sum for the total price, and print for a message prepared for output.
Hints
- Start with the kind of value being stored, such as score, count, total, or message.
- Keep the built-in name available for its normal function meaning.
- A compound descriptive name is acceptable, such as max_score.
A good variable name prevents two problems at once: it keeps the built-in accessible and tells readers what the variable represents.
Key Takeaways
- Built-in functions such as max, len, sum, and print should be treated as reserved variable names.
- Assigning a variable with a built-in's name shadows that built-in in the affected scope.
- The assignment may appear harmless, but a later call to the expected function can fail.
- The most reliable solution is to choose descriptive names such as max_score or item_count.
- Avoiding built-in name collisions improves both reliability and readability.
Key Takeaways
- Python allows variables to use built-in function names, but doing so hides the built-in in that scope.
- Shadowing often causes a delayed bug: the assignment creates the problem, while a later call reveals it.
- Names such as max, len, sum, and print should be treated as reserved for practical purposes.
- Descriptive alternatives such as max_score, item_count, and total_amount prevent collisions and clarify intent.