Programming with Modules

What will we cover?
  • What modules are about
  • Functions as modules
  • Using module files
  • Writing our own functions and modules
  • What's a Module?

    The 4th element of programming involves the use of modules. In fact its not strictly necessary, and using what we've covered so far you can actually write some pretty impressive programs. However as the programs get bigger it becomes harder and harder to keep track of what's happening and where. We really need a way to abstract away some of the details so that we can think about the problems we are trying to solve rather than the minutae of how the computer works. To some extent that's what Python, BASIC etc already do for us with their built in capabilities - they prevent us from having to deal with the hardware of the computer, how to read the individual keys on the keyboard etc.

    The idea of programming with modules is to allow the programmer to extend the built in capabilities of the language. It packages up bits of program into modules that we can 'plug in' to our programs. The first form of module was the subroutine which was a block of code that you could jump to (rather like the GOTO mentioned in the branching section) but when the block completed, it could jump back to wherever it was called from. That specific style of modularity is known as a procedure or function. In Python and some other languages the word module has taken on a specific meaning which we will look at shortly, but first let's consider functions a bit more closely.

    Using Functions

    Before considering how to create functions let's look at how we use the many, many functions that come with any programming language (often called the library).

    We've already seen some functions in use and listed others in the operators section. Now we'll consider what these have in common and how we can use them in our programs.

    The basic structure of a function is as follows:

    aValue = someFunction(anArgument, another, etc...)
    

    That is a variable takes on a value obtained by calling a function. The function can accept 0 or many arguments which it treats like internal variables. Functions can call other functions internally. Let's consider some examples in our various languages to see how this works:

    BASIC: MID$(str$,n,m)

    This prints the next m characters starting at the nth in str$. (Recall that names ending in '$' in BASIC signify a string)

    time$ = "MORNING EVENING AFTERNOON"
    PRINT "Good";MID$(time$,8,8)
    

    This prints out "Good EVENING".

    BASIC: ENVIRON$(str$)

    This returns the specified Environment Variable str$.

    PRINT ENVIRON$("PATH")
    

    Prints the current PATH as set in DOS (usually via the autoexec.bat file).

    Tcl: llength L

    Returns the length of list L

    set a {"first" "Second" "third"} # 3 element list
    puts [llength $a]  # output is '3'
    

    Note: almost everything in Tcl is a function(or as Tcl prefers to term it, a command). This leads to some awkward syntax but makes it very easy for the computer to read Tcl programs. This is important because Tcl stands for Tool Control Language and was designed to be embedded in other programs as a macro language like Visual Basic for Applications(VBA) in Microsoft products. You can actually embed Python in the same way but Tcl is unique in that it was designed first and foremost with embedding in mind.

    Python: pow(x,y)

    x = 2   #  we'll use 2 as our base number
    for y in range(0,11):
       print pow(x,y)    # raise 2 to power y, ie 0-10
    

    Here we generate values of y from 0 to 10 and call the built-in pow() function passing 2 arguments: x and y. On each call the current values of x and y are substituted into the call and the result is printed.

    Note: The exponentiation operator, ** is equivalent to the pow() function.

    Python: dir(m)

    Another useful function built in to python is dir which, when passed the name of a module, gives back a list of valid names - often functions - in that module. Try it on the builtin functions:

    print dir(__builtins__)
    

    Note: To use it on any other module you need to import the module first otherwise Python will complain that it doesn't recognise the name.

    Before doing much else we'd better talk about Python modules in a bit more detail.

    Using Modules

    Python is an extremely extendable language (as indeed is Tcl) in that you can add new capabilities by importing modules. We'll see how to create modules shortly but for now we'll play with some of the standard modules that ship with Python.

    sys

    We met sys already when we used it to exit from Python. It has a whole bunch of other useful functions too. To gain access to these we must import sys:

    import sys # make functions available
    sys.exit() # prefix with 'sys'
    
    If we know that we will be using the functions a lot and that they won't have the same names as functions we have already imported or created then we can do:
    from sys import *  # import all names in sys 
    exit() # can now use without specifying prefix 'sys'
    

    Other modules and what they contain

    You can import and use any of Pythons modules in this way and that includes modules you create yourself. We'll see how to do that in a moment. First though, I'll give you a quick tour of some of Python's standard modules and some of what they offer:

    Module nameDescription
    sys Allows interaction with the Python system:
  • exit() - exit!
  • argv - access command line arguments
  • path - access the system path
  • ps1 - change the '>>>' python prompt!
  • os Allows interaction with the operating system:
  • open - open a file
  • system - execute a system command
  • mkdir - create a directory
  • getcwd - find the current working directory
  • string Allows manipulation of strings
  • atoi/f/l - convert string to integer/float/long
  • find - find substring
  • split - break into 'words'
  • upper/lower - case conversion
  • re Allows manipulation of strings with Unix style
    regular expressions
  • search - find pattern anywhere in string
  • match - find at beginning only
  • split - break into fields separated by pattern
  • sub,subn - string substitution
  • math Allows access to many mathematical functions:
  • sin,cos etc - trigonometical functions
  • log,log10 - natural and decimal logarithms
  • ceil,floor - ceiling and floor
  • pi, e - natural constants
  • time time(and date) functions
  • time - get the current time (expressed in seconds)
  • gmtime - convert time in secs to UTC (GMT)
  • localtime - convert to local time instead
  • mktime - inverse of localtime
  • sleep - pause program for n seconds
  • These are just the tip of the iceberg. There are literally dozens of modules provided with Python, and as many again that you can download. (A good source is the Vaults of Parnassus.) Look at the documentation to find out how to do internet programming, graphics, build databases etc.

    The important thing to realize is that most programming languages have these basic functions either built in or as part of their standard library. Always check the documentation before writing a function - it may already be there! Which leads us nicely into...

    Defining our own functions

    OK, So we know how to use the existing functions how do we create a new function? Simply by defining it. That is we write a statement which tells the interpreter that we are defining a block of code that it should insert on demand elsewhere in our program.

    So lets create a function that can print out a multiplication table for us for any value that we provide as an argument. In BASIC it looks like:

    SUB TIMES (N%)
    FOR I = 1 TO 12
        PRINT I; "x"; N%; "="; I * N%
    NEXT I
    END SUB
    

    And we can call it like this:

    PRINT "Here is the 7 times table..."
    TIMES(7)
    

    Note: We defined a parameter called N% and passed an argument of 7 . The local variable N% inside the function took the value 7 when we called it. We can define as many parameters as we want in the function definition and the calling programs must provide values for each parameter. Some programming languages allow you to define default values for a parameter so that if no value is provided the function assumes the default. We'll see this in Python later.

    In Python the TIMES function looks like:

    def times(n):
        for i in range(1,13):
            print "%d x %d = %d" % (i, n, i*n)
    

    And is called like:

    print "Here is the 9 times table..."
    times(9)
    

    Note that these functions do not return any values (they are really what some languages call procedures). In fact notice that the BASIC version actually uses the keyword SUB rather than FUNCTION. This stands for subroutine, a little used term from the age of assembler programming that in BASIC means a function that does not return a value. Python by contrast uses the term def which is short for 'define' and that which follows is assumed to be a function.

    Recall that I mentioned the use of default values? One sensible use for these would be in a function which returned the day of the week. If we call it with no value we mean today, otherwise we provide a day number as an argument. Something like this:

    # a day value of -1 => today
    def dayOfWeek(DayNum = -1):
        days = ['Monday','Tuesday',
                'Wednesday','Thursday', 
                'Friday', 'Saturday', 'Sunday']
                    
        # check for the default value        
        if DayNum == -1:
            # Use the time module functions to get current time
            # see the table above and the official module documentation
            import time
            theTime = time.localtime(time.time())
            DayNum = theTime[6]
        return days[DayNum]
    

    Note: We only need to use the time module if the default parameter value is involved, therefore we defer the import operation until we need it. This would provide a slight performance improvement if we never had to use the default value feature of the function.

    Now we can call this with:

    print "Today is: %s" % dayOfWeek()
    # remember that in computer speak we start from 0
    # and in this case we assume the first day is Monday.
    print "The third day is %s" % dayOfWeek(2)
    

    Back to multiplication again....

    What if we wanted to define a function that just returned the values of the multiplication as an array of numbers? In BASIC it looks like:

    FUNCTION TIMES% (N%)
        DIM VALUES(12) AS INTEGER
        FOR I = 1 to 12
            VALUES(I) = I*N%
        NEXT I
        RETURN VALUES
    END FUNCTION
    

    And in Python:

    def times(n):
        # create new empty list
        values = []  
        for i in range(1,13):
            values.append(i*n)
        return values
    

    This would be pretty dumb, because it's easier to just calculate i*n on demand. But hopefully you see the idea. A more practical function which returns a value might be one which counts the words in a string. You could use that to calculate the words in a file by adding the totals for each line together.

    The code for that might look something like this:

    def numwords(s):
        list = split(s) # list with each element a word
        return len(list) # return number of elements in list
    
    for line in file:
        total = total + numwords(line) # accumulate totals for each line
    print "File had %d words" % total
    

    Now if you tried it, you'll know that it didn't work. What I've done is a common design technique which is to sketch out how I think the code should look but not bothered to use the absolutely correct code. This is sometimes known as Pseudo Code or in a slightly more formal style Program Description Language (PDL).

    Once we've had a closer look at file and string handling, a little later in the course, we'll come back to this example and do it for real.

    Tcl Functions

    We can also create functions in Tcl, of course, and we do so using the proc command, like so:

    proc times {m} {
        for {set i 1} {$i <= 12} {incr i} {
            lappend results [expr $i * $m]
    	}
        return $results
    }
    

    Note that by using the Tcl lappend list command I automatically create a list called results and start adding elements to it.

    A Word of Caution

    Tcl is a little different in the way it deals with functions. In fact you may have noticed that I have been calling the builtin Tcl functions commands. That's because in Tcl every command you type at the Tcl prompt is actually a function call. Most languages come with a set of keywords like for, while, if/else and so on. Tcl makes all of these control keywords commands or functions. This has the interesting, confusing and very powerful effect of allowing us to redefine builtin control structures like this:

    set i 3
    while {$i < 10} {
        puts $i
        set i [expr $i + 1]
        }
    

    As expected this prints out the numbers from 3 to 9 (1 less than 10). But let's now define our own version of the while command:

    proc while {x y} {
      puts "My while now"
    }
    
    set i 3
    while {$i < 10} {
        puts $i
        set i [expr $i + 1]
        }
        
    

    This does nothing but print the message "My while now". The expression and command sequence are ignored because Tcl treats them as parameters to the while function and the while function expects them but ignores them! So you can see how we define procedures in Tcl and how we can abuse that to create very confusing programs - don't do it unless you have a very good reason!

    Creating our own modules

    So now we can create our own functions and call these from other parts of our program. That's good because it can save us a lot of typing and, more importantly, makes our programs easier to understand because we can forget about some of the details after we create the function that hides them. (This principle of wrapping up the complex bits of a program inside functions is called information hiding for fairly obvious reasons.) But how can we use these functions in other programs? We create a module.

    Python Modules

    A module in Python is nothing special. It's just a plain text file full of Python program statements. Usually these statements are function definitions. Thus when we type:

    from sys import *
    

    we effectively copy the contents of sys.py into our program, almost like a cut n' paste operation. (its not really like that but the concept is OK). In fact in some programming languages (noteably C++) the translator literally does simply copy module files into the current program as required.

    So to recap, we create a module by creating a Python file containing the functions we want to reuse in other programs. Then we just import our module exactly like we do the standard modules. Easy eh? Let's do it.

    Copy the function below into a file by itself and save the file with the name timestab.py

    def print_table(multiplier):
        print "--- Printing the %d times table ---" % multiplier
        for n in range(1,13):
            print "%d x %d = %d" % (n, multiplier, n*multiplier)
    

    Now at the Python prompt type:

    >>> import timestab
    >>> timestab.print_table(12)
    

    Heh presto! You've created a module and used it.

    Important Note:If you didn't start Python from the same directory that you stored the timestab.py file then Python might not have been able to find the file and reported an error. If so then you can create an environment variable called PYTHONPATH that holds a list of valid directories to search for modules (in addition to the standard modules supplied with Python).

    Creating environment variables is a platform specific operation which I assume you either know how to do or can find out!

    Modules in BASIC and Tcl

    What about BASIC? That's more complex.... In QBASIC and other older varieties there is no real module concept. You have to manually cut n' paste from previous projects into your current one using your text editor. However in Visual Basic there is a module concept and you can load a module via the Integrated Development Environment (IDE) File|Open Module... menu. There are a few restrictions as to what kind of things you can do inside a BASIC module but since we're not using Visual Basic on this course I won't go into that any further. (Note: there is a cut down version of Visual Basic known as the COM Controls Edition, CCE, available for free download on Microsoft's website if you feel like experimenting. Also Windows 98, 2000 and IE5 all install a cut down version of VB called VBScript which you can use in files ending .vbs)

    Finally Tcl, as ever(!), takes a somewhat eclectic, but nonetheless interesting, path with regard to reusing modules (or as it prefers to call them libraries).

    At the simplest level you can just create a file of Tcl functions as we do in Python and then, in your program, source the file. This literally causes the interpreter to read your file and those programs become available for use. But there is a more interesting option:

    You can create your files as above, put them all in a directory/folder and then run a mk_index command. This builds an index of all the functions and files in the folder. Then in your program you simply call the required function and the Tcl interpreter will realize the function is not available and automatically look in the index file. It will then source the relevant source file from the library and execute the function.

    Once sourced the function stays available so there is little performance overhead involved. The only snag is that the programmer must avoid having more than one function with the same name. This feature of Tcl is known as autoloading.

    Next we'll take a look at files and text handling and then as promised revisit the business of counting words in a file. In fact we're eventually going to create a module of text handling functions for our convenience.

     
    Things to remember
  • Functions are a form of module
  • Functions return values, procedures don't
  • Python modules normally consist of function definitions in a file
  • Create new functions with the def keyword in Python
  • Use SUB or FUN in BASIC and proc in Tcl
  •  
    Previous  Contents  Next 


    If you have any questions or feedback on this page send me mail at: alan.gauld@btinternet.com