Introduction |
This programming assignment is designed to show how Python functions can define
other Python code (in this case, a class) in an unexpected way: the function
can build a huge string that represents the definition of a Python class and
then call exec on it, which causes Python to define that class just as
if it were written in a file and imported (in which case Python reads the
file as a big string and does the same thing).
Your code will heavily rely on string formatting operations: I suggest using
the str.format method to do the replacements: now is a good time to
learn about this function if you don't know already know it; but you are free
to use whatever string processing tool(s) you want.
I suggest that you first read the description below and define/test/debug as much of the Point class as you can, writing it directly in Eclipse (especially the __getitem__, __eq__, _asdict, _make, and _replace methods). You might want to write a small batch file to help you test this class. Once you have written/debugged the code for the Point class, define the general pnamedtuple function, which when given the appropriate arguments (for the Point class: pnamedtuple('Point', 'x y')) constructs a huge string that contains exactly the same code as the Point class that you wrote. Much of the code from your Point class will be turned into strings and made generic: generalized for calls to pnamedtuple with different arguments. Use the .format method to replace the generic parts with the actual strings needed for the class being defined. Download the program3 project folder and use it to create an Eclipse project. Read and run the miniexample.py module, which performs a similar but simpler task: it illustrates how to write the keep function as a small string. All the elements needed to write the pnamedtuple function appear in here in a simplfied form (see especially the call to the join function). Put your pnamedtuple in the pcollections.py module, which can be tested in the standard driver or by writing code in the script at the bottom of the pcollections.py module. I recommend that you work on this assignment in pairs, and I recommend that you work with someone in your lab section (so that you have 4 hours each week of scheduled time together). These are just recommendations. Try to find someone who lives near you, with similar programming skills, and work habits/schedule: e.g., talk about whether you prefer to work mornings, nights, or weekends; what kind of commitment you will make to submit program early. Only one student should submit all parts of the the assignment, but both students' UICnetID and name should appear in a comment at the top of each submitted .py file. A special grading program reads this information. The format is a comment starting with Submitter and Partner (when working with a partner), followed by a colon, followed by the student's UCInetID (in all lower-case), followed by the student's name in parentheses (last name, comma, first name -capitalized appropriately). If you omit this information, or do not follow this exact form, it will require extra work for us to grade your program, so we will deduct points. Note: if you are submitting by yourself, and do NOT have a partner, you should OMIT the partner line and the "...certify" sentence. For example if Romeo Montague (whose UCInetID is romeo1) submitted a program that he worked on with his partner Juliet Capulet (whose UCInetID is jcapulet) the comment at the top of each .py file would appear as: # Submitter: romeo1(Montague, Romeo) # Partner : jcapulet(Capulet, Juliet) # We certify that we worked cooperatively on this programming # assignment, according to the rules for pair programmingIf you do not know what the terms cooperatively and/or rules for pair programming mean, please read about Pair Programming before starting this assignment. Print this document and carefully read it, marking any parts that contain important detailed information that you find (for review before you turn in the files). The code you write should be as compact and elegant as possible, using appropriate Python idioms. |
pnamedtuple |
Problem Summary:Write a function named pnamedtuple that is passed information about a named tuple: it returns a reference to a class object from which we can construct instances of the specified named tuple. We might use this class as follows:from pcollections import pnamedtuple Point = pnamedtuple('Point', 'x y') p = Point(0,0) ...perform operations on p using methods defined in the Point classPlease note that although many of the examples in this description use the Point class, your pnamedtuple function must work for all legal calls to pnamedtuple. For example the batch-self-check file uses descriptions (some legal, some not) of the Triple class. I created six templates (one big, two medium, three small), which are each strings that have parts to fill in using the format method; all but the small strings are triple-quoted, multi-line strings, that look like large chunks of Python code (see miniexample.py in the download to help understand this paragraph, because it has similar templates).
Note calling the following format method on the string
In many cases, the arguments I passed to the format calls were computed by list comprehensions turned into strings by calling the .join method (the opposite of the .split method). See the miniexample for an example of everything working together to define a function by filling in a template with .format. Finally, my solution is about 150 lines (including blank lines and comments, and a solution to the extra credit part), and that is divided between Python code (50% of the lines) and string templates that specify Python code (50% of the lines). Details
Of course, our pnamedtuple function should work for Point as illustrated above, but should also work for any other legal call to create a named tuple. The actual namedtuple class in Python is specified and implemented differently than the requirements of this assignment. You may not use Python's actual namedtuple in this assignment. TestingThe pcollections.py module includes a script that calls driver.driver(). The project folder contains a bsc.txt file (examine it) to use for batch-self-checking your function. These are rigorous but not exhaustive tests.Note that when exceptions are raised, they are printed by the driver but the Command: prompt sometimes appears misplaced.
You can write other code at the bottom of your pcollections.py module to
test the pnamedtuple function, or type code into the driver as
illustrated below.
Notice the default for each command is the command previously entered.
Files for batch_test (see bt.txt for an example) just contain commands that will be executed; many are calls to the print function, which show the result of the print. Remember that your pnamedtuple function can print on the console, for debugging purposes, the string it is about to exec so you can look for errors there (just eyeball whether the code correct). The show_listing function (defined in the pnamedtuple function) display a string on the console, numbering its lines (useful when exec finds an error: it reports a line number that show_listing shows). Finally, I have also included two programs that David Kay published in ICS-31 that use Python's namedtuple (with those names changed to pnamedtuple). It would be a good idea to test you pnamedtuple in these contexts, and in the script with other numbers/names of fields. |