Concepts / Introduction to Namespaces

Introduction to Namespaces

A name in another namespace is reached by qualifying it: the namespace name, then ::, then the name, as in std::cout and My_code::main.

  • 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

Imagine your program is written in one place, but a name you need was defined inside a different namespace. Your code needs some way to point at that name from where it currently stands. This article covers the most direct way to do that: writing the namespace name right next to the name you want. Once you see that pattern, the rest of the namespace story becomes much easier to follow.

What do you think happens?

Can a program contain two different functions that are both called main?

  • No, a name can only be used once in a program

  • Yes, if the two functions live in different namespaces

Reveal answer
Answer:

Yes, if the two functions live in different namespaces

The source explains that two functions both called main can coexist because they live in different namespaces. Each one is reached through its own namespace, so the names do not collide. The rest of this article shows how that works.

Reading a Qualified Name

Every name lives in some namespace. When the name you want lives in a namespace other than the one your code is currently working in, you reach it by qualifying it. You attach the namespace name to the front of the name and join the two with the scope operator, written as a double colon. The result is called a qualified name.

The source gives two examples of the pattern. The first is std::cout, where cout is reached through the standard-library namespace named std. The second is My_code::main, where a name called main is reached through a namespace named My_code. Both follow the same shape, so learning to read one lets you read the other.

stdnamespace name::scope operator joining themcoutname being reachedqualifiesjoins to
In std::cout, which part is the namespace name, which is the :: qualifier, and which is the name being reached?

Read a qualified name from left to right. The left-hand part is the namespace name. The double colon in the middle is the operator that joins the namespace to the name. The right-hand part is the name being accessed. In std::cout, std is the namespace name, :: is the joining operator, and cout is the name reached inside the standard-library namespace. Reading the pieces in this order makes it clear that the whole expression refers to something inside a specific namespace, not something sitting at the top level.

The pattern does not change depending on what kind of name is being reached. The qualifier-plus-name form is the same whether the reached name is a function or some other kind of name. Once you can identify the three parts, you can read any qualified name the same way.

Worked example

Taking My_code::main apart

Identify the three parts of the qualified name My_code::main.

  1. 1
    Find the left-hand part

    My_code is the namespace name. It tells you which namespace the name belongs to.

  2. 2
    Find the operator

    The double colon in the middle joins the namespace to the name.

  3. 3
    Find the right-hand part

    main is the name being accessed inside the My_code namespace.

Result

The whole expression refers to a main that lives inside My_code, not a main at the top level of the program.

Where the Real main Lives

The global namespace is the region that is not local to any defined namespace, class, or function. The real main() is defined there. Because it sits in the global namespace, it has no namespace qualifier at all. You do not write a namespace name in front of it.

A main placed inside a named namespace such as My_code is different. It is explicitly placed inside My_code, so reaching it requires the qualifier, written as My_code::main. The two functions share the name main but are located in different places. Because they live in different namespaces, both can coexist in the same program.

Global namespacemain()the real main, no qualifierMy_codemain()reached as My_code::maincontainscontains
Which namespace contains the real main(), and how does its position differ from a main() defined inside My_code?

Using-Directives as a Second Route

Qualification is the simplest and most direct route to a name in another namespace. It can become repetitive, however, if you need many names from the same namespace. Writing the namespace name and :: before every use adds up quickly. For that situation the source introduces a second route called the using-directive.

A using-directive gives your code access to names in a namespace so that you do not have to write the qualifier every time. The source's example is access to names in the standard-library namespace. Once that access is in place, you can refer to names such as cout without repeating std::.

The qualified and unqualified forms refer to the same underlying name. The using-directive does not create a different name. It only changes how much typing you need at each use. This is why qualification is still the baseline: it always works, and the using-directive is a convenience layered on top of it.

std::coutfull qualified name at eachusecoutqualifier not written ateach useSimplest, most directrouteConvenience, lesstypingrelies onrelies on
How do the two routes differ when reaching a name from another namespace: writing the full qualified name each time versus bringing the namespace in with a using-directive?

Mistakes Beginners Make with Qualified Names

  • Common mistake

    Reading std::cout as one unexplained word

    Why it fails

    The double colon is an operator with a meaning. It separates the namespace from the name being reached.

    Do this instead

    Split the expression into three parts: the namespace name std, the operator ::, and the name cout.

  • Common mistake

    Assuming every main is the same function

    What it looks like

    The real main() and My_code::main both have the name main.

    Why it fails

    Two functions can share a name when they live in different namespaces.

    Do this instead

    Check the namespace each function belongs to. The real main() is in the global namespace, while My_code::main is inside My_code.

  • Common mistake

    Thinking a using-directive changes which name is used

    Why it fails

    The qualified and unqualified forms refer to the same underlying name. The directive only changes how you write it.

    Do this instead

    Treat a using-directive as a shortcut for typing, and remember that qualification is always available.

Practice Reading Qualified Names

EASY

Take the qualified name My_code::main. Identify the namespace name, the operator, and the name being reached. Then say whether this main is the real main() and why.

Hints
  • Read the expression from left to right, the same way you read std::cout.
  • The real main() is defined in the global namespace and has no namespace qualifier.
  • A main that needs the My_code qualifier is placed inside My_code.

Key Takeaways

  • A name in another namespace is reached by qualification: the namespace name, then the scope operator ::, then the name, as in std::cout and My_code::main.
  • The real main() is defined in the global namespace and has no qualifier, while a main inside My_code must be reached as My_code::main.
  • Two functions both called main can coexist because they live in different namespaces.
  • A using-directive gives access to names in a namespace without repeating the qualifier, and it only changes how conveniently names are written; the underlying name is the same.

More concepts starting with I