5.2. Python names and namespaces¶
We have already been introduced to the Python concept of a name. An explicit though somewhat technical discussion of the subject of names can found in the Python docs. The following discussion is simplified, and focuses on the basic idea of namespaces.
When a Python program is loaded and run, your computer’s memory contains a set of things we will simply call objects. For example, when you load a module that contains a function definition, that places a function object into memory. The function object is Python’s representation of a program. When a program is run it often creates further objects. For example a program might compute some numbers and return them as a list. That list of numbers is an object taking up space in memory:
>>> ScoreList = get_test_scores(python__for_ss_midterm)
Objects in memory may or may not have names. Generally objects get named at creation time and generally they get named because they might come in handy at some later time. So the Python command above makes the result of executing the get_test_scores function retrievable by storing it in the name ScoreList.
A very common way of assigning a name to an object is a variable assignment command like the one above. But it is not the only way. The following Python code block constructs a certain function object and assigns it to the name main:
def main():
if len(sys.argv) >= 2:
name = sys.argv[1]
else:
name = 'World'
print 'Hello', name
So when you load a Python module with an import statement, it executes all the function definitions in the file, placing a set of functions objects in memory and associating each of them with a name. If the file contains variable assignment commands, that introduces more names and possibly more objects. Other constructions, such as class definitions (to be covered later), use up more names. The moral, then, is that importing modules uses up names.
Python is very consistent about the syntax of names. The way to find out what a name denotes is to type the name to the Python prompt and hit “Return”. Beginners sometimes get confused by this property. After typing in the above function definition, typing the name just returns the function reference:
>>> main
<function main at 0x100493cf8>
If you want to execute the function, you need to add the parentheses and any arguments. In the case of a function with no arguments like main, you still need the parentheses:
>>> main()
Hello World
Python is untyped, meaning any name can be used for any object. If it has been used for one type of object, any naming construction, such as a variable assignment, can overrule the old name, and assign it to a competely different kind of object. So the unwary beginner might well decide to reuse the name main as a variable and type:
>>> main = 1
Once this is done the name main denotes an integer and the function definition is lost. When the unwary beginner then tries to call main as a function, he sees:
>>> main()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
That is, this is exactly the same error as
>>> 1()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
The integer “1” is not a function and can’t be called. Thus, keeping track of what uses names have been put to is an important part of programming. One way to avoid problems like the one above is to use different kinds of names (for example, different case-conventions) for variable names and functions. But this is really the tip of an iceberg, and good programming practice will not melt the entire iceberg.
The example above suggests the larger problem. The name main is a name any programmer might use for the main function in a module. Indeed, some programming languages encourage this practice. But then what happens when two modules with functions named main are loaded? Should the one loaded second just overwrite the one loaded first? Probably not.
One way to solve this problem is to get more creative about naming functions. For example, if the above definition comes from a module named hello.py, we might just call the function hello_world unstead of main. But this solution leaves much to the discretion of individual programmers, and has significant limitations. As your knowledge of Python grows, you will find yourself loading more and more Python modules, many of them containing code (and therefore names) you have never looked at. This raises the likelihood of a nameclash, and therefore a mysterious and hard to detect bug, considerably. Since naming conventions and the ability to use them consistently vary considerably, Python has implemented a more general solution: When a module hello is loaded with the command,:
>>> import hello
and the module defines a function main, the name main is not associated with the function definition. Instead the name hello.main is. The way to call “main” is to type:
>>> hello.main()
Hello World
If the programmer then types,:
>>> main = 1
the name main is set to denote the integer and the name hello.main in unaffected, so the command main.hello() will work as intended.
The technical name for the Pythonic solution is namespaces. That is, by default, each module has a namespace of its own, the names beginning with the module name followed by “.”. Thus the name space of the “hello” module is all names beginning with “hello.”, the name space of a module named “goodbye” is “goodbye.”, and if both define functions named “main”, one will be accessible under the name “hello.main” and the other under the name “goodbye.main”.
Namespaces are an important Pythonic idea, as you will see if you type:
>>> import this
The main place they will affect you as a Python beginner is in how you you use the names of imported modules. The other place where namespaces play a key role is in class definitions, which we will talk about in Section Classes and class attributes.
The names available in a Python namespace can be viewed by accessing its directory. This is done with the dir command.
We illustrate dir
by import the math module and listing
its names:
>>> import math
>>> dir(math)
['__doc__', '__file__', '__name__', '__package__', 'acos', 'acosh', 'asin',
'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh',
'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor',
'fmod', 'frexp', 'fsum', 'gamma', 'hypot', 'isinf', 'isnan', 'ldexp',
'lgamma', 'log', 'log10', 'log1p', 'modf', 'pi', 'pow', 'radians', 'sin',
'sinh', 'sqrt', 'tan', 'tanh', 'trunc']
5.2.1. The _builtin_ namespace¶
Every name available in Python belongs to some namespace. The namespace containing all the names available when you start up Python is called __builtins__. Every name in __builtins__ belongs to the toplevel namespace and therefore does not have to be prefixed with a module name. The dir command will list those names:
>>> dir(__builtins__)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BufferError',
'By tesWarning', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError',
'Exception', ' False', 'FloatingPointError', 'FutureWarning', 'GeneratorExit',
'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'KeyError',
'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented',
'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning',
'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration',
'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True',
'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError',
'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError',
'Warning', 'ZeroDivisionError', '_', '__debug__', '__doc__', '__import__', '__name__',
'__package__', 'abs', 'all', 'any', 'apply', 'basestring', 'bin', 'bool', 'buffer',
'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile',
'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate',
'eval', 'execfile', 'exit', 'file', 'filter', 'float', 'format', 'frozenset',
'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int',
'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals',
'long', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord',
'pow', 'print', 'property', 'quit', 'range', 'raw_input', 'reduce', 'reload', 'repr',
'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str',
'sum', 'super', 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']
Discussing the purpose of all these names goes well beyond the bounds of this section. Suffice it to say for now that four main kinds of Python objects are listed:
Exceptions
Functions
Types
None