Concepts / Understanding Modules and Namespaces

Understanding Modules and Namespaces

Imagine you are writing a program that calculates square roots repeatedly. With the standard import, every call looks like math.sqrt(16), math.sqrt(25), math.sqrt(100). The math. prefix appears dozens of times. The from … import statement offers a shortcut: bring sqrt directly into your workspace so you can write sqrt(16) instead. This section explores what that shortcut actually does, what it costs, and when it is worth using.

  • Programming

The Repeated Prefix Problem

Imagine calculating square roots repeatedly. With standard import, each call uses the module prefix: math.sqrt(16), math.sqrt(25), and math.sqrt(100). The from ... import statement provides a shorter form by making sqrt available directly, so the calls become sqrt(16), sqrt(25), and sqrt(100). The important question is not only how to shorten the call, but what changes in the namespace when the import executes.

selects fromcontainsbecomes available asfrom math importsqrtimport statementmathmodulesqrtlocal namesqrtfunction object
What changes in the local namespace after executing from math import sqrt?

Tracing the Namespace

Following sqrt from import to call

Determine which name is added and what happens when sqrt(16) is called after from math import sqrt.

Before the import: The selected name sqrt has not yet been added to the local namespace by this statement.

The import executes: The statement selects sqrt from the math module and creates the local name sqrt.

The call is evaluated: Python looks up sqrt in the local namespace, finds the square root function object, and calls it with 16.

The result appears: The result of sqrt(16) is 4.0.

After the import, sqrt can be called directly, and sqrt(16) produces 4.0.

After from math import sqrt executes, exactly one new name is added by that statement: sqrt. The name is available directly in the local namespace. The module name math is not thereby made available through this statement, so this import does not make math.sqrt available as a consequence of importing only sqrt.

sqrtavailable directlymath.sqrtrequires mathmathnot added by this statement
After from math import sqrt, which names can be used directly and which require a math. prefix?

One Object, Two Names

The import does not copy the sqrt function into a separate function object. Instead, it creates the local name sqrt and makes that name point to the same function object that exists inside the math module. The module's name and the local name are two references to one object. When sqrt(16) is called, Python finds the local name and calls that original function object.

refers torefers tomath.sqrtname in modulesqrt functionone function objectsqrtlocal name
How does the local name sqrt connect to the original function object stored in the math module?

Predicting Available Names

What do you think happens?

After from sys import argv, which use is available directly: argv or sys.version?

  • Only argv
  • Only sys.version
  • Both
  • Neither
Reveal answer

Answer: Only argv

The statement brings argv into the namespace, but it does not import sys itself. Therefore argv works directly, while sys.version fails because the name sys was not imported.

StatementName available directlyOther usable form described by the source
from sys import argvargvsys.version is unavailable because sys was not imported
from os import getcwdgetcwdThe selected name is available directly
from os import pathpathpath.exists('.') is available
argvdirectly availablesys.versionsys not importedosdirectly availablepathdirectly available
Which names are available after selecting names from sys and os?

Choosing the Import Style

Import styleHow the call is writtenMain clarity effect
Standard importmath.sqrt(16)The origin of sqrt is visible in the call
Direct importsqrt(16)The call is shorter, but readers must inspect the imports to find the origin

Use from ... import when one specific name is used very frequently, the source module is obvious from context, and there is no risk of collision with another name in the program. The source pack describes a geometry program where sqrt is used three times in quick succession, the math module is unambiguous, and no other sqrt exists. In that situation, the shorter form reduces visual clutter without sacrificing clarity.

Standard import is safer for clarity when the origin of a name may be unclear or when several modules contribute names. If multiple names are imported from different modules, the benefit of direct imports decreases because the names' origins are hidden. The source specifically identifies import os and import sys as clearer in that situation.

provides prefix forused asmathmodule name availablesqrtselected name availablemath.sqrtprefixed callsqrtdirect call
How do the module name and available function names differ between import math and from math import sqrt?

Collision Risk

sqrtexisting local namesqrtdirect imported namemodule.sqrtmodule-qualified namehidden originmust inspect imports
What happens when a local name already exists or another imported name uses the same name?
  • Assuming that importing one member also imports the module name.

    The statement imports argv into the namespace, not sys itself.

    Fix: Track the exact name listed after import. argv is available directly; sys.version is not made available by that statement.

  • Treating a direct import as if it created a copied function.

    The local name refers to the same function object that exists in the math module.

    Fix: Think of the import as creating another name for the original object.

  • Choosing a direct import when the origin of the name may be unclear.

    Readers must inspect the import statements to discover where each name comes from.

    Fix: Prefer standard imports when visible origins improve readability or when name collisions are possible.

Practice the Trace

EASY

Consider these two statements: from os import path and from os import getcwd. Identify the names that become directly available, then decide whether path.exists('.') can be used and whether os.getcwd() can be used from these statements.

Hints
  • List only the names written after import.
  • A direct import makes the selected name available without its module prefix.
  • Check whether os itself was imported.

Checking the Imported Names

Determine which calls are available after from os import path and from os import getcwd.

List the selected names: The directly imported names are path and getcwd.

Check the path call: path.exists('.') is available because path was imported directly.

Check the module-prefixed call: os.getcwd() is not made available by these statements because os itself was not imported as a direct name.

path.exists('.') is available directly through path, while os.getcwd() requires os to have been imported.

Key Takeaways

  1. from module import name adds the selected name directly to the local namespace.
  2. Only the names listed after import are brought in by that statement.
  3. The new local name refers to the same object that exists in the module; it is not a copied function.
  4. Direct imports shorten frequently used calls, but they hide the name's origin and can create collision risks.
  5. Use direct imports when the name is specific and frequent, the source is obvious, and collisions are unlikely; otherwise, standard imports are clearer.

Key Takeaways

  • from ... import selects particular names and places those names in the local namespace.
  • After from math import sqrt, sqrt is available directly, while importing only sqrt does not make the module name math available through that statement.
  • The local name and the module's name refer to the same original function object.
  • Standard import makes origins visible; direct import makes repeated calls shorter.
  • Choose from ... import when frequency, context, and collision safety justify the shorter form.