Appendix 2: Structuring Complex Code¶
Adapted from: https://openbookproject.net/thinkcs/python/english3e/modules.html#creating-your-own-modules
Breaking a Long Code into Separate Modules¶
Up until now we have been keeping all our code in a single file. For large or complex programmes this can be difficult to manage. Fortunately it is possible to import functions from external modules, and use them in our current script. Putting values and functions in their own module is as simple as saving it in a separate Python script file, then importing the functions and variables using an import statement such as
import MY_MODULENAME as my
and accessing the objects within it using the DOT
syntax:
NEW_VARNAME = my.VARIABLE
or
FNAME = my.FUNCTION
All we need to do to create our own modules is to save our script as
a file with a .py
extension (this is why you don’t use spaces in Python filenames!).
The following code is saved in a script saved as "mytools.py"
in the same folder as the main notebook or python script (take a look at it).
It’s good practice to use the filename as the first line comment of the module:
#mytools.py
def remove_at(pos, seq):
return seq[:pos] + seq[pos+1:]
We can now use our module in scripts we write, and access all the functions and variables in them.
To do so, we must first import
the module.
import mytools as my
s = "A string!"
print(my.remove_at(4, s))
Notice that the .py
file extension is not used when importing.
Python expects the file names of Python modules to end in .py
, so the file extension is not included in the import
statement.
Note also that the module should usually be located in the same folder as your main Python script.
Namespaces in Modules¶
The use of modules makes it possible to break up very large programs into manageable sized parts, and to keep related parts together. In the following example the name of the module file is the comment on the first line.
First module, saved as "my_module.py"
has these contents (take a look):
# my_module.py
question = "What is the meaning of Life, the Universe, and Everything?"
answer = 42
Second module, saved as "my_module2.py"
looks like this:
# my_module2.py
question = "What is your quest?"
answer = "To seek the holy grail."
We can now import both modules and access question
and answer
in each:
import my_module as my
import my_module2 as my2
print(my.question)
print(my2.question)
print()
print(my.answer)
print(my2.answer)
Exercise:¶
Create and use two of your own modules.
Go to the Jupyter Notebooks main menu page and then:
Click “New” (top right),
Set the name from
untitled.txt
to match the one below<NAME>.py
cut and paste the code in (don’t forget to save it afterwards).
Create the following two python script files:
You will need to restart the kernel in your Notebook using the [⟳] button if you change the
.py
modules so that the new version is loaded usingimport
.
Parameter module (use the filename in the head-line comment):
#my_params.py
import math
pi=math.pi
a=7.0
b=12.0
Module for my functions:
#my_functions.py
import my_params as myp
PI = myp.pi
def circle_area(r):
return PI*r*r
Run the code below
import my_functions as funcs
import my_params as pars
print(funcs.PI)
print(pars.a)
print(funcs.circle_area(a))
Correct the error in the cell below
### BEGIN SOLUTION
import my_functions as funcs
import my_params as pars
print(funcs.PI)
print(pars.a)
print(funcs.circle_area(pars.a))
### END SOLUTION
Visibility of Variables¶
Note that a module cannot see the variables inside other modules, or in the main script unless we tell it about them. We can do this by having the modules themselves import things, or by declaring global variables.
Global variables can get confusing and are outside the scope of this introductory unit, but if you are interested there is lots of information available for your self-study (search for “Python global local variables”).
Exercise:¶
Create a script named
newmodule.py
.Add variables
myage
set to your current age, andyear
set to the current year.Create another module named
newmodule2.py
.Add attributes
myage
set to 0, andyear
set to the year you were born.Now create a new script, import both of the modules above and write the following two lines:
print(“Have I had my birthday this year yet?\n”) print((newmodule.myage - newmodule2.myage) == (newmodule.year - newmodule2.year))
* It should print `True` if you've had your birthday this year!
* **Dont forget to restart the kernel [⟳] if you change anything in the `.py` files and save**
### BEGIN SOLUTION
import newmodule, newmodule2
print("Have I had my birthday this year yet?\n")
print((newmodule.myage - newmodule2.myage) == (newmodule.year - newmodule2.year))
### END SOLUTION
You can also change variables.
E.g., if the above returned True
set your age a year younger (or +=1
if it was False
) using:
newmodule.myage -= 1 # takes one off the previous value
print(newmodule.myage)
and rerun the print lines again.