Please note that this introduction is made for Python 2.7
By popular demand from previous students, we have put together a small collection of exercises to get you started with Python and Ruby. We start with some of the basic stuff like getting to know the interactive environments and converting between different data types, and then move on to simple functions, classes, tools and a graphical user interface.
While you don't need to do exactly these exercises to pass the course, they are a good starting point to learn the language.
Start the interactive Python interpreter by typing python on the command line. If installed, you might also want to try the IPython shell, started by issuing ipython at the terminal. (Cool features about IPython include tab-completion of method names.)
When Python starts, it will look something like this:
Python 2.4.3 (#1, Dec 9 2006, 21:49:24) [GCC 4.0.1 (Apple Computer, Inc. build 5367)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>>
Now it is time to play around with the interactive language. If you have not seen something like this before, take ample time to be blown away. If your computer is set-up properly, you should have readline support, which means Emacs style commands should work fine.
Let's start by evaluating a few simple expressions and watch how the terminal behaves.
1. 42 2. "Hello World" 3. x (this should raise an error) 4. [] 5. [1, 2, 3, 4] 6. x = "Deeo" 7. x 8. y = { 1 : "First", "Second" : 2 }'
Ok, that was a few Python literals and expressions. Use google or your books if you have trouble understanding what happens. If all else fails, note down questions for the Python tutoring session (T1). Then, let's do something a little more complicated.
1. 4+47 2. 3245434*23423434 3. 10/3 4. 10/2.0 5. 4**2 6. "==" * 20 7. 20 * "==" 8. y
If y raises an error, you should type in y = { 1 : "First", "Second" : 2 } again. This creates a dictionary object (a hash table) with 1 and "Second" as keys and "First" and 2 as values mapped to by the respective keys. To get a feel for what you can do with dictionaries, you can use the dir BIF (BIF is the standard abbreviation for built-in-function) on it to list its method. Go ahead:
1. dir(y)
The result should look something like this:
['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__str__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
So, let's go ahead and use it.
1. y.keys() 2. y.values() 3. y[1] 4. y["Second"] 5. y["Second"] += 1 6. y["Second"] 7. y
This simple piece of code will iterate over all keys of y and print it corresponding values:
for key in y.keys(): print y[key]
A nicer way of printing the hashmap would be something like this:
for key in y.keys(): print key, " --> ", y[key]
Even though in this case it will make the code messier, let's take this opportunity to show off Python's string interpolation mechanism:
for key in y.keys(): print "%s --> %s" % ( key, y[key] )
Python lists and hash maps are extremely powerful, light-weight data structures. You'll find that a lot of time, there will be no need to create classes to keep data around. Lists and hash maps will do fine.
Before ending this installment, lets do this:
1. y.keys
What you get back when you omit the parentheses is a pointer to the method of the actual object. Thus you can do this:
1. m = y.keys 2. m() 3. len(m())
Last, let's examine the __doc__ attribute. Many Python objects have a __doc__ attribute that contains a documentation string for the actual thing. For example, the docstring for the keys() method is "D.keys() -> list of D's keys".
1. m.__doc__
Now you are ready to start converting between data types. Move along.
Python has the following built-in functions (BIFs) for data conversion. Conversion yields copies, it does not coerce the object in-place.
* ord(char) (ordinal value for character) * chr(int) (character for ordinal value) * str(obj) (converts anything to a string, eq. with Java's toString()) * repr(obj) (returns the string representation as Python code) * int(str, [base]) (converts a string to an int, e.g., from "23" to 23. * float(str) (as above but for floats) * long(str, [base]) (as above but for longs) * hex(int) (convert integer to hexadecimal string) * oct(int) (convert integer to octal string) * eval(str) (convert from string to Python object, with
Where [...] are optional parameters.
Using the for loop construct as outlined above, write a small loop, still in the interpreter, for printing the ascii values of the letters A-Z. To our aid comes the Python BIF range that operates like this:
>>> range(0,10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
The for loop construct that we used above was a for each loop, so by use of ord, chr, range, and print, you should be able to get this output from a 2-line program, but for capital letters:
a has ord 97 b has ord 98 c has ord 99 ... y has ord 121 z has ord 122
The eval BIF is powerful and dangerous. It takes a string and evaluates it as if it was Python code, returning the result. This means that you could for example read a text file from disk and execute it, thus:
f = open("textfile") # given that the file is # called exactly "textfile" eval("f.read()")
Still in the interactive Python environment, type (make sure to not omit the indentation for the third line):
MESSAGE = "Hello " def greet(person): print MESSAGE + person + "!"
This defines a function greet that takes a single argument, person and prints the standard greeting message. Now go ahead and call the method:
greet("Tobias")
The dynamic typing allows even this:
greet([])
which of course makes the program blow up in our faces. (Can you see how you can use the tricks of the previous section to make the code always work?)
Let's now define a classic method -- factorial:
def fac(n): if n: return n * fac(n-1) else: return 1
Try it with really big numbers. You'll be surprised. The greet function is still around, so lets do this:
MESSAGE = "The result is: " greet(fac(27))
This wont work unless you didn't fix up the greet function to deal with whatever kind of data you feed it.
A very nice Python feature, which reminds me of Smalltalk in its readability is the use of parameter names in method calls allowing parameters to be passed in any order:
def example(fst, snd, thrd): print fst, snd, thrd example(snd = "dole", fst = "Ole", thrd = "doff")
Exception handling works much like expected (if you know Java):
def example(a, b): try: return a / b except Exception: print "Division by zero" return 0 example(4,5) example(4,0)
Try to find out how to:
cat (simple file open/read)
The cat utility reads files sequentially, writing them to the standard output. Write your own cat utility that takes a number of file names as command line arguments and for each file writes it to standard out. If the -n option is specified, the lines should be properly numbered starting from 1 with each file. If the file is 800 lines long, line 1 should have number __1 (where _ are spaces).
Feel free to play around more with cat or do man cat to get more information on the util.
grep (regular expressions)
The command line tool grep is invoked like this:
grep PATTERN [FILE...]
When it runs, searches the named input FILEs (or standard input if no files are named, or the file name - is given) for lines containing a match to the given PATTERN. By default, grep prints the matching lines. The pattern should be a regular expression.
Re-using the skeleton code from cat, implement a grep utility of your own. Feel free to implement the additional bells and whistles that you find in grep too.
(What happens if PATTERN is a faulty regular expression?)
Rename
(This exercise will drill you more in the use of regular expressions, but also in the OS libraries for moving files etc.)
In many *nix systems there is a file renaming utility called rename written in Perl. The rename utility will allow more advanced batch file renaming. For example, to rename all files matching "*.bak" to strip the extension, you might say
rename 's/\.bak$//' *.bak
To translate uppercase names to lower, you'd use
rename 'y/A-Z/a-z/' *
Read up on regular expressions if the above commands are not clear to you. Hints: s/a/b/ substitutes all occurrences of a with b. Further, y/ab/12/ transliterates all occurrences of a with 1 and b with 2. $ matches the end of the line (or before newline at the end). A good place to read is in the man pages:
man rename man perlre man perlop
Comparing File Trees
Using the Python libraries, create a utility to compare the contents of two directories (including subdirectories). The utility should be invoked like this:
beefheart$ ./dircmpDirectory1 Directory2
where
Files are considered equivalent if they
have the same name
and size. If you want, you can extend the tool to also
compute checksums for files of the same size and compare
checksums to capture content. Or some other method.
Navigating the Python libraries is quite simple. Start
looking at the [module index] and go from there. As static
type information is lacking, you will find that the libraries
look a bit different from, say [JavaDoc]. If you are
intereted in how well dynamic libraries can be documented,
the Apple Objective-C Cocoa libraries are a good place to
start.
The Windows .ini file format is very simple. Each file has 0
or more clauses. A clause starts with the name on the form
[NAME-OF-CLAUSE] followed by 0 or more key-value maps on the
form key: value. Keys need not be unique, but have a
precedence order -- a key that appears again will "override"
the all previous ones.
Your task is to write a program that converts from .ini files
to XML. For example:
Your program should generate this XML file (or equivalent):
Note that the duplicate key has been removed.
TBW
TBW
Parsing Java code with RE and create a dependency graph in DOT
format.
TBW
Build an editor and previewer for [
http://docutils.sourceforge.net/rst.html ]reStructuredText that
renders to HTML and previews in a separate window. Try to handle
errors too.
Write a Python program that parses a number of text files for
words and counts the word frequency. The program should be
started as follows:
The program should then keep track of how many times each
word occurs in the files (you need not keep track of in which
files the words were found.) The output of the program should
be the unique set of all words encountered with each word on
its own line. Following the word should be its frequency:
Sample input (contents of a text file):
Sample output:
Addition
Rewrite the program to not use a standard Python collection,
but make your own. I suggest you use a binary tree, where the
tree is ordered on the words and the frequency is the "data".
Make sure you overload all methods and operators you used
before, so that you ideally only have to change the line
where you first create the collection.
Other additions
You may want to add command line arguments to you program. A
-o flag would perhaps be appropriate, this flag would specify
an output file other than stdout. Something like this:
Another flag could be one to have the output printed in
ascending or descending order.
Hint: check out the getopt module.
The following links might also be
helpful (both for beginners and
advanced users). Links collected by
Louppe Gilles.
Regular Expressions
[JAN GUILLOU]
arn: bad
hamilton: worse
fagerhult: great
arn: worst
[PETER BRATT]
book: IB och hotet mot vår säkerhet
collaborations: Jan Guillou
Classes
Class Dependency Graph
GUI: Editor & Previewer
Misc
./wordfreq.pl infile1 infile2 infileN
Donec 1
Lorem 2
adipiscing 1
amet 2
consectetuer 1
dolor 2
elit 1
hendrerit 1
ipsum 2
sit 2
tellus 1
tempor 1
./wordfreq.pl -o outfile infile1 infile2 infileN
Links
- (Official) Python documentation:
http://docs.python.org/index.html
- (Official) Python tutorial:
http://docs.python.org/tutorial/index.html
- (Official) Python standard library reference:
http://docs.python.org/library/
- PEP8 (Style Guide for Python):
http://www.python.org/dev/peps/pep-0008/
- Dive Into Python (a very practical introduction to Python):
http://www.diveintopython.org/