Concepts / The Global Namespace

The Global Namespace

A name in another namespace is most simply reached by qualifying it, written as namespace_name::name, as in std::cout.

  • Programming
Interactive lab

Try it: Scope: Local, Enclosing, Global, Built-in

How Python looks up a name Local → Enclosing → Global → Built-in, why assigning to a name inside a function makes it local (and raises UnboundLocalError if it is read first), and what global, nonlocal and closures change.

How it works

  1. Before a function runs, Python marks every name assigned inside it as local to that function, unless it is declared global or nonlocal.
  2. Reading a name searches the local namespace, then enclosing functions, then the module's globals, then the built-ins; the first hit wins.
  3. A local name read before it has a value raises UnboundLocalError (Python does not fall back to the global).
  4. global x makes assignments go to the module namespace; nonlocal x makes them go to the nearest enclosing function.
  5. A function's local frame disappears when it returns, unless an inner function (a closure) still uses its variables.

Default run (10 steps): Ready: Local shadows global. Every name is looked up Local, then Enclosing, then Global, then Built-in. … Finished. Printed: inside: 99 / outside: 10.

Simplified: The lab's own small Python interpreter runs a fixed, hand-written script (you choose the variant and the values, never the code); nothing is executed as real Python. Every script was run in CPython 3.12 with the same inputs and the lab reproduces its output and error messages. Built-ins shows only the names the script used.

Educational simulation

Loading the simulation…

A Name That Lives Somewhere Else

Suppose a program has a name that belongs to one namespace, and the code that needs that name sits outside the namespace. How does the code reach the name? The question is simple to state, but the answer depends on a detail that is easy to miss: the code has to say which namespace it means, so that the name is found in the correct place and not confused with a name of the same spelling somewhere else.

What do you think happens?

Code outside a namespace needs a name that is defined inside that namespace. What information should the code give so the name is found in the right place?

Reveal answer
Answer:

It should name the namespace the name belongs to, and then give the name itself. The name is reached by qualifying it with the namespace name, written as namespace_name::name.

The qualifier is what separates a name from another name with the same spelling that lives in a different namespace.

Two Names Spelled the Same

Imagine two different namespaces that each contain a name spelled count. Inside each namespace, count means something different. If the code only wrote count, the reader, and the program, would have no way to tell which one is meant. The final word is identical in both places, so the spelling alone cannot identify the name.

text
Notes on the code
  • Inventory is the namespace on the left of the first expression
  • Sales is the namespace on the left of the second expression
  • count is spelled the same in both, and the qualifier is what tells them apart
Worked example

Tracing which count is meant

Two namespaces each define a name spelled count. Code outside both namespaces must use the count from Sales, not the one from Inventory. How does the code say which one it means?

  1. 1
    Identify the name that is needed

    The needed name is count, but there are two names with that spelling, one per namespace.

  2. 2
    Identify the namespace that owns the wanted name

    The wanted count is the one inside Sales.

  3. 3
    Attach the namespace name and the double colon

    Write the namespace name, then two colons, then the name: Sales::count.

  4. 4
    Check that the expression is unambiguous

    Sales::count identifies exactly one name, while the bare word count would not say which namespace it came from.

Result

The code writes Sales::count, and the qualifier makes the reference unambiguous.

Reading a Qualified Name

The most direct way to access a name in another namespace is to qualify it with the namespace name. You write the namespace name, then two colons, then the name itself. The general form is namespace_name::name. The source gives two examples: std::cout and My_code::main. In each case the part before the double colon identifies the namespace, and the part after it identifies the name inside that namespace.

stdthe namespace::connects namespace to namecoutthe name inside std
In std::cout, which part is the namespace, which is the member, and what does the double colon connect?

Read each expression from left to right. The left side names the container and the right side names the item inside it. The qualifier is what makes the reference unambiguous: the same final word can appear in more than one namespace, and the qualifier says which one you mean.

The Global Namespace and the Real main()

The global namespace holds names that are not local to a defined namespace, class, or function. The source makes one specific point about it: the real main() is defined there. This matters when you read a qualified name such as My_code::main. That expression refers to a name inside the My_code namespace. It is a different name from the real main(), which sits at the global level and is not local to any defined namespace. Seeing the same word in two places is exactly the situation the qualifier exists to separate.

Global namespacenames not local to anamespace, class, orfunctionmain()the real main, defined hereMy_codea defined namespacemaina different name, qualifiedas My_code::mainstdthe standard-librarynamespacecoutreached as std::cout
The real main() sits at the global level, while My_code::main is a separate name inside the My_code namespace, and std::cout is a name inside std.

Crossing the Namespace Boundary

Code outside a namespace reaches a name in that namespace through the boundary. The name itself does not move. It still belongs to its namespace, and the code gives a path to it. Qualification is that path, written at the point of use. Each time the code needs the name, the qualifier travels with it.

Worked example

Reaching cout from outside std

Code that sits outside the std namespace wants to print through the name cout, which is defined inside std. Trace how the name is reached.

  1. 1
    Stand outside the namespace

    The code is not inside std, so the bare word cout is not enough to find the name.

  2. 2
    Name the namespace

    Write std, the namespace that owns cout.

  3. 3
    Add the double colon and the name

    The full expression is std::cout, which the source gives as an example of qualification.

Result

The name is found inside std through the qualified expression std::cout, and the namespace boundary is crossed without changing where cout is defined.

Using-Directives Versus Qualification

Qualifying every use of a name works, but it can become repetitive. The source introduces a second mechanism for the standard-library namespace: the using-directive. A using-directive gives you access to names in a namespace, so that you can refer to those names without writing the qualifier each time. The source presents it as the tool to reach for when you want access to names in the standard-library namespace.

Notice what the using-directive does and does not do. It changes how you are allowed to refer to names, not where those names are defined. The names still belong to their namespace. The directive is a way of reaching them more conveniently in the code that follows it.

std::coutwritten at each usecoutreferred to withoutrepeating the qualifierNamespace named atpoint of useevery reference carries thequalifierNames still belong tostdonly the way of referringchanges
After a using-directive, which names can the code see unqualified, and how does that differ from writing std::cout each time?
FeatureQualificationUsing-directive
What it gives youAccess to a name by naming its namespaceAccess to names in a namespace without repeating the qualifier
Where the namespace is namedAt each point of useOnce, so later code can omit it
Where the name is definedUnchanged, inside its namespaceUnchanged, inside its namespace
Typical readingExplicit about every sourceShorter, convenient when one namespace is used heavily

Both techniques reach the same name; they differ in how much naming the code repeats.

Choosing Between the Two Approaches

Both techniques give you access to a name in another namespace, so the choice is about how the code reads and how clearly it identifies its sources. Qualification names the namespace at the point of use, which makes every source visible on the line where it is used. A using-directive lets you omit that naming at the point of use, which is convenient when one namespace is used heavily. Use the guiding questions below to decide.

  1. 1
    Ask whether the name is used once or only a few times in the code. A single or occasional use favours qualification, which keeps the source visible.
  2. 2
    Ask whether one namespace is used heavily throughout the code. Heavy use of one namespace favours a using-directive, which saves repeating the qualifier.
  3. 3
    Ask whether two namespaces could supply names with the same spelling. If they could, qualification protects you, because the qualifier says which one is meant.
  4. 4
    Ask whether the reader needs to see the source of each name on the line where it appears. If yes, qualify the name.
  5. 5
    Remember that a using-directive changes only how names are written, not where they are defined.

Mistakes Learners Make With Qualified Names

  • Common mistake

    Treating the qualifier as optional decoration

    What it looks like

    Writing cout where std::cout is needed, from code outside std

    Why it fails

    The bare word does not say which namespace owns the name, so the reference is ambiguous when the same spelling appears elsewhere.

    Do this instead

    Write the namespace name, then the double colon, then the name: std::cout.

  • Common mistake

    Reading My_code::main as the real main()

    What it looks like

    Assuming My_code::main is the program entry point because it contains the word main

    Why it fails

    The real main() is defined in the global namespace, not inside My_code. My_code::main is a different name inside My_code.

    Do this instead

    Read the left side of the double colon as the container. The real main() is the global one, and My_code::main lives inside My_code.

  • Common mistake

    Believing a using-directive moves a name into another namespace

    Why it fails

    A using-directive only changes how names are referred to in the code that follows it. The names still belong to their original namespace.

    Do this instead

    Think of the directive as a shorter way to reach names, not a change in where they are defined.

  • Common mistake

    Reading the expression from right to left instead of left to right, which confuses the container with the item inside it

Practice Choosing a Form

MEDIUM

Code outside the namespace My_code needs the name main that is defined inside My_code. Another part of the same program needs the real main() that is defined in the global namespace. Write the form each part should use, and explain in one sentence why the two forms must differ.

Hints
  • The qualified name has the form namespace_name::name.
  • The real main() is not local to any defined namespace, so it does not need a namespace qualifier of its own.
  • Compare the spelling main in both places and ask what separates them.
MEDIUM

A file has many references to cout from code outside std, and a reader complains that the file is hard to scan. Decide whether a using-directive is appropriate here, and justify your choice using the idea that it changes only how names are written.

Hints
  • Consider how heavily the std namespace is used in this file.
  • Consider whether the reader still needs to see the source of each name.

Key Takeaways

  • A name in another namespace is reached by qualifying it, written as namespace_name::name, such as std::cout or My_code::main.
  • In a qualified name, the part before the double colon identifies the namespace and the part after it identifies the name inside that namespace.
  • The global namespace holds names that are not local to a defined namespace, class, or function, and the real main() is defined there, separate from any name like My_code::main.
  • A using-directive gives access to names in a namespace without repeating the qualifier, and it changes how names are written, not where they are defined.
  • Qualification shows the source of each name at the point of use, while a using-directive is convenient when one namespace is used heavily.

Related concepts

More concepts starting with T