Writing Reusable Functions
Reusable design requires these two uses to behave differently when necessary.
One File, Two Uses
A Python file can serve two purposes: it can be run as a standalone program, or it can be imported so that another program can use its functions. Reusable design requires these two uses to behave differently when necessary. The __name__ attribute gives the file information about how it is being used, allowing the file to protect test or demonstration code from running during an import.
Tracing the Module Identity
Python automatically sets __name__ according to the way a file is being used. For the file the user runs directly, __name__ is set to the exact string '__main__'. For a file that is imported, __name__ is set to the module's name instead. This value is the signal that lets the file distinguish standalone execution from imported use.
What do you think happens?
Suppose a file named module_using_name is run directly and then imported from another script. What will __name__ contain in each situation?
Reveal answer
It contains '__main__' when run directly and 'module_using_name' when imported.
Python assigns '__main__' to the file run directly. When another script imports the file, Python assigns the module's name instead.
The Main Guard
The main guard is the condition if __name__ == '__main__':. It checks whether the file is the program being run directly. If the condition is true, the indented block executes. If the file is imported, __name__ contains the module name instead, so the condition is false and that block is skipped.
When this file is run directly:
5
When this file is imported:
The function add is available, but the print statement inside the main guard does not execute.Reusable Definitions and Standalone Tests
A Calculator Module
Design a file that offers add and multiply functions to importing programs while keeping its test output for standalone execution.
- 1Define reusable functions
Place the add and multiply functions in the module so another programmer can import and use them.
- 2Add standalone test code
Place calls that test the functions inside the if
__name__== '__main__': block. - 3Run the file directly
The file has
__name__equal to '__main__', so the test calls execute and their output is shown. - 4Import the file
The file has
__name__equal to its module name, so the main-guard condition is false. The functions are available, but the test output does not run.
One file supports both reusable function access and separate standalone testing without automatically producing test output during import.
def add(first, second):
return first + second
def multiply(first, second):
return first * second
if __name__ == '__main__':
print(add(2, 3))
print(multiply(2, 3))- 1Python reaches the function definitions, making add and multiply available in the module.
- 2Python evaluates the
__name__condition. - 3During direct execution, the condition is true because
__name__equals '__main__'. - 4The two print calls execute and display the test results.
- 5During import, the condition is false, so the print calls are skipped while the functions remain available.
- The add function is a reusable definition.
- The multiply function is a reusable definition.
- The main guard checks how the file is being used.
- The test calls execute when the file is run directly.
5
6Exact Syntax Matters
Common mistake Using one underscore instead of the double underscores in __name__.
What it looks likeif _name_ == '__main__':Why it failsThe pattern depends on the
__name__attribute. Changing its spelling does not perform the intended check.Do this insteadWrite __name__ with two underscores before name and two underscores after it.
Common mistake Comparing against a different string.
What it looks likeif __name__ == 'main':Why it failsThe direct-execution value is the exact string '
__main__'.Do this insteadCompare __name__ to '__main__', including both underscores.
Common mistake Putting standalone test code outside the guard.
What it looks likeprint(add(2, 3))Why it failsThat code is not protected by the condition, so it is not separated from the reusable module code.
Do this insteadIndent standalone test or demonstration calls beneath if __name__ == '__main__':.
Practice the Decision
A file contains a reusable function and a print statement inside if __name__ == '__main__':. Predict what happens in these two cases: first, the file is run directly; second, another script imports it. State whether the function is available and whether the print statement executes in each case.
Hints
- Start by identifying the value of
__name__in each situation. - The condition is true only when
__name__equals '__main__'. - The source material states that imported functions remain available while protected test output does not run.
- 1For direct execution, assign
__name__the value '__main__'. - 2For import, assign
__name__the module's name instead. - 3Evaluate the main-guard condition in each case.
- 4Separate the reusable function from the protected print or test code.
Reusable Module Checklist
- 1When a file is run directly, Python sets
__name__to '__main__'. - 2When a file is imported, Python sets
__name__to the module's name. - 3The condition if
__name__== '__main__': runs its indented block only during direct execution. - 4Reusable functions can be made available to importing programs without automatically running standalone test or demonstration output.
- 5The exact double-underscore spelling and the exact string '
__main__' are required.
Use the main guard when a file is intended to work both as a reusable module and as a standalone program. This pattern keeps test or demonstration code from cluttering programs that import the module and signals that the file has both uses.
Key Takeaways
- The
__name__attribute identifies whether a file is being run directly or imported. - Direct execution sets
__name__to '__main__'; importing sets it to the module's name. - The main guard protects standalone test and demonstration code.
- Functions can remain available for import while protected output is skipped.
- Always use the exact syntax if
__name__== '__main__':.