Python was voted Programming Language of the Year in 2007 and 2010 by TIOBLE software Index and is currently the 8th most widely used language in the world. Python is a multi-paradigm language - object-oriented, functional, and procedural. This lab demonstrates two of Python's important features: 1) treating functions as first class objects and 2) coroutines.
expandtab
, tabstop
, and syntax
on vi
before saving your Python script. You can see all of your vi settings with
the vi command:
:set all
PART I. Functions as First-Class Objects.
For this portion of the lab you will solve several problems that involve
passing a function as a parameter to another function.
If you have worked with C you know how messy it is to pass a pointer
to a function as an argument. In C this functionality
is a kludge since a C function differs fundamentally
from a data type that you normally pass to a function.
Treating a function as a first-class object means that you can pass a function
to a function as seamlessly as you would pass any other object. You can
think of a function as just another type of data.
Passing a function as an argument is the basis for callback function support in JavaScript, PHP and jQuery. Callbacks are supported in a number of web scripting languages primarily to add asynchronous program flow for event handlers. See callbacks.html for a simple example of this concept. Passing a function as an object is an inherent feature of functional languages beginning with Lisp. Anonymous (lambda) functions are applied to input as the input is on its way to another function application. Passing named and anonymous (lamdba) functions to another function is standard operating procedure in functional languages.
Before starting this lab, get an overview of the basics of Python in this test.py script. You should have a working knowledge of each line of code before starting the lab. Have the Python docs handy for in-depth explanation of the concepts. Python is a scripting language. Like lisp, you can also execute commands within the interpreter that you end up in by just typing python. See the readme for instructions on how to execute a script. Your job in this part of the lab is to add two Python functions to lab09.py. Each function will access lab09.data. The specifications for the functions given below. Start by copying the script and data file:
$ cp /home/fac/melissa/public_html/cs350-f15/examples/week09/lab09.py . $ cp /home/fac/melissa/public_html/cs350-f15/examples/week09/lab09.data .Run the script. Make sure you understand everything in the existing code. Note: there is no error checking on input for the data file. For example, a blank line will crash the script. You can assume good input. Note: if you know what you are doing, you only need to add ten or so lines of code to the file. Specifications:
File lab09.data is structured like this: 10 15 20 0 17 STEP 1. Add a function 'my_mean' to lab09.py that will take as arguments the list read in from lab09.data and a boolean function over x that returns true for x > 0. Function my_mean will return the mean for the values that meet the constraints of the boolean function. E.g.: my_mean (lambda x: x > 0, list) will return the mean for the nonzero numbers in the list. In my_mean you will 1) apply the boolean function to each number in the list; 2) count and sum the number of values for which B returns true; and 3) return the mean. Hint: Don't forget to initialize sum and count as real numbers. My_mean is similar in concept to the function my_map that is given to you in lab09.py. STEP 2. Add a function 'my_filter' to lab09.py that will take as arguments the list read in from lab09.data and a boolean function. My_filter will return the filtered list of values that meet the constraints of the function. E.g.: my_filter (lambda x: (x % 2) == 0, list) will return a list that contains only even numbers.PART II. Coroutines in Python.
Coroutines are supported in Python with calls to yield (which blocks waiting for a request) and next or send (which initiates a request with and without a message). Each time next or send is called the coroutine blocking on yield resumes execution.
Your job is to add two coroutines to lab09.py. Start by making some changes to a script that implements coroutines called coroutines.py. Grab the script here:
$ cp /home/fac/melissa/public_html/cs350-f15/examples/week09/coroutines.py .You will eventually integrate coroutines.py into lab09.py to make a single script. For now it is probably easier to work with coroutines.py and combine the two scripts later but it is up to you. Script coroutines.py uses Python lists. If the syntax is not intuitive, read the documentation on Python lists here. The script implements a variation on the producer/consumer algorithm. The producer in this case sends jobs to the consumer. The consumer waits for the producer to send a job, performs the job, and sends something back to the producer. Normally both producer and consumer yield to each other but in this algorithm only the consumer is blocking (waiting on the producer to give it the go-ahead to continue). Make these changes to coroutines.py:
STEP 1. In the existing program, main (all code in the script that is not in a subroutine) is acting as the producer. Modify the code so that the producer is its own function. The producer function will be called from main after the jobs data structure is initialized. The producer then starts the consumer.
STEP 2. Modify the script so that the data structure shared between the producer and the consumer is a list of 2-tuples instead of a list of strings (see test.py for an example of this). The list is shown here:
jobs = [("wash",11),("dry",22),("fold",33)]The first element in the 2-tuple is the job name. The second element in the 2-tuple is the job number. Modify all job requests to account for the different data type; i.e., the add request will look like this:
printjob(s.send(("add","iron",44)))
THREE. Finally, integrate your coroutines into lab09.py. Modify lab09.py to read in one additional cmdline argument in as an integer (see test.py for how to convert string to integer). Add the integer read in to the id value for each job; i.e., initialize your structure like this:
jobs = [("wash",11+n),("dry",22+n),("fold",33+n)]Sample output:
$ ./lab09.py lab09.data 99 PART I. original list: [10, 15, 20, 0, 17] odds: [15, 17] squared: [100, 225, 400, 0, 289] mean: 15.5 PART II. Cmdline arg: 99 Producer starting. Consumer starting. wash,110 dry,121 fold,132 ADD iron,44 wash,110 dry,121 fold,132 iron,44 REMOVE iron,44 fold,132 wash,110 dry,121 Producer Done.HOW YOUR LAB WILL BE GRADED
Your script must reside here:
/home/stu/{username}/cs350/lab09/lab09.py
Your work will be graded by my script after the deadline.