python tutorials

By amalbose

1.2K 9 3

More

python tutorials

1.2K 9 3
By amalbose

Classes

Introduction

One thing that you will get to know about programming, is that programmers like to be lazy. If something has been done before, why should you do it again?

That is what functions cover in python. You've already had your code do something special. Now you want to do it again. You put that special code into a function, and re-use it for all it is worth. You can refer to a function anywhere in your code, and the computer will always know what you are talking about. Handy, eh?

Of course, functions have their limitations. Functions don't store any information like variables do - every time a function is run, it starts afresh. However, certain functions and variables are related to each other very closely, and need to interact with each other a lot. For example, imagine you have a golf club. It has information about it (i.e. variables) like the length of the shaft, the material of the grip, and the material of the head. It also has functions associated with it, like the function of swinging your golf club, or the function of breaking it in pure frustration. For those functions, you need to know the variables of the shaft length, head material, etc.

That can easily be worked around with normal functions. Parameters affect the effect of a function. But what if a function needs to affect variables? What happens if each time you use your golf club, the shaft gets weaker, the grip on the handle wears away a little, you get that little more frustrated, and a new scratch is formed on the head of the club? A function cannot do that. A function only makes one output, not four or five, or five hundred. What is needed is a way to group functions and variables that are closely related into one place so that they can interact with each other.

Chances are that you also have more than one golf club. Without classes, you need to write a whole heap of code for each different golf club. This is a pain, seeing that all clubs share common features, it is just that some have changed properties - like what the shaft is made of, and it's weight. The ideal situation would be to have a design of your basic golf club. Each time you create a new club, simply specify its attributes - the length of its shaft, its weight, etc.

Or what if you want a golf club, which has added extra features? Maybe you decide to attach a clock to your golf club (why, I don't know - it was your idea). Does this mean that we have to create this golf club from scratch? We would have to write code first for our basic golf club, plus all of that again, and the code for the clock, for our new design. Wouldn't it be better if we were to just take our existing golf club, and then tack the code for the clock to it?

These problems that a thing called object-oriented-programming solves. It puts functions and variables together in a way that they can see each other and work together, be replicated, and altered as needed, and not when unneeded. And we use a thing called a 'class' to do this.

Creating a Class

What is a class? Think of a class as a blueprint. It isn't something in itself, it simply describes how to make something. You can create lots of objects from that blueprint - known technically as an instance.

So how do you make these so-called 'classes'? very easily, with the class operator:

Code Example 1 - defining a class

# Defining a class

class class_name:

[statement 1]

[statement 2]

[statement 3]

[etc]

Makes little sense? Thats ok, here is an example, that creates the definition of a Shape:

Code Example 2 - Example of a Class

#An example of a class

class Shape:

def __init__(self,x,y):

self.x = x

self.y = y

description = "This shape has not been described yet"

author = "Nobody has claimed to make this shape yet"

def area(self):

return self.x * self.y

def perimeter(self):

return 2 * self.x + 2 * self.y

def describe(self,text):

self.description = text

def authorName(self,text):

self.author = text

def scaleSize(self,scale):

self.x = self.x * scale

self.y = self.y * scale

What you have created is a description of a shape (That is, the variables) and what operations you can do with the shape (That is, the fuctions). This is very important - you have not made an actual shape, simply the description of what a shape is. The shape has a width (x), a height (y), and an area and perimeter (area(self) and perimeter(self)). No code is run when you define a class - you are simply making functions and variables.

The function called __init__ is run when we create an instance of Shape - that is, when we create an actual shape, as opposed to the 'blueprint' we have here, __init__ is run. You will understand how this works later.

self is how we refer to things in the class from within itself. self is the first parameter in any function defined inside a class. Any function or variable created on the first level of indentation (that is, lines of code that start one TAB to the right of where we put class Shape is automatically put into self. To access these functions and variables elsewhere inside the class, their name must be preceeded with self and a full-stop (e.g. self.variable_name).

Using a class

Its all well and good that we can make a class, but how do we use one? Here is an example, of what we call creating an instance of a class. Assume that the code example 2 has already been run:

Code Example 3 - Creating a class

rectangle = Shape(100,45)

What has been done? It takes a little explaining...

The __init__ function really comes into play at this time. We create an instance of a class by first giving its name (in this case, Shape) and then, in brackets, the values to pass to the __init__ function. The init function runs (using the parameters you gave it in brackets) and then spits out an instance of that class, which in this case is assigned to the name rectangle.

Think of our class instance, rectangle, as a self-contained collection of variables and functions. In the same way that we used self to access functions and variables of the class instance from within itself, we use the name that we assigned to it now (rectangle) to access functions and variables of the class instance from outside of itself. Following on from the code we ran above, we would do this:

Code Example 4 - accessing attributes from outside an instance

#finding the area of your rectangle:

print rectangle.area()

#finding the perimeter of your rectangle:

print rectangle.perimeter()

#describing the rectangle

rectangle.describe("A wide rectangle, more than twice\

as wide as it is tall")

#making the rectangle 50% smaller

rectangle.scaleSize(0.5)

#re-printing the new area of the rectangle

print rectangle.area()

As you see, where self would be used from within the class instance, its assigned name is used when outside the class. We do this to view and change the variables inside the class, and to access the functions that are there.

We aren't limited to a single instance of a class - we could have as many instances as we like. I could do this:

Code Example 5 - More than one instance

longrectangle = Shape(120,10)

fatrectangle = Shape(130,120)

and both longrectangle and fatrectangle have their own functions and variables contained inside them - they are totally independent of each other. There is no limit to the number of instances I could create.

Lingo

Object-oriented-programming has a set of lingo that is associated with it. Its about time that we have this all cleared up:

* When we first describe a class, we are defining it (like with functions)

* The ability to group similar functions and variables together is called encapsulation

* The word 'class' can be used when describing the code where the class is defined (like how a function is defined), and it can also refer to an instance of that class - this can get confusing, so make sure you know in which form we are talking about classes

* A variable inside a class is known as an Attribute

* A function inside a class is known as a method

* A class is in the same category of things as variables, lists, dictionaries, etc. That is, they are objects

* A class is known as a 'data structure' - it holds data, and the methods to process that data.

Inheritance

Lets have a look back at the introduction. We know how classes group together variables and functions, known as attributes and methods, so that both the data and the code to process it is in the same spot. We can create any number of instances of that class, so that we don't have to write new code for every new object we create. But what about adding extra features to our golf club design? This is where inheritance comes into play.

Python makes inheritance really easily. We define a new class, based on another, 'parent' class. Our new class brings everything over from the parent, and we can also add other things to it. If any new attributes or methods have the same name as an attribute or method in our parent class, it is used instead of the parent one. Remember the Shape class?

Code Example 6 - the Shape class

class Shape:

def __init__(self,x,y):

self.x = x

self.y = y

description = "This shape has not been described yet"

author = "Nobody has claimed to make this shape yet"

def area(self):

return self.x * self.y

def perimeter(self):

return 2 * self.x + 2 * self.y

def describe(self,text):

self.description = text

def authorName(self,text):

self.author = text

def scaleSize(self,scale):

self.x = self.x * scale

self.y = self.y * scale

If we wanted to define a new class, lets say a square, based on our previous Shape class, we would do this:

Code Example 7 - Using inheritance

class Square(Shape):

def __init__(self,x):

self.x = x

self.y = x

It is just like normally defining a class, but this time we put in brackets after the name, the parent class that we inherited from. As you see, we described a square really quickly because of this. That's because we inherited everything from the shape class, and changed only what needed to be changed. In this case we redefined the __init__ function of Shape so that the X and Y values are the same.

Let's take from what we have learnt, and create another new class, this time inherited from Square. It will be two squares, one immediately left of the other:

Code Example 8 - DoubleSquare class

# The shape looks like this:

# _________

#| | |

#| | |

#|____|____|

class DoubleSquare(Square):

def __init__(self,y):

self.x = 2 * y

self.y = y

def perimeter(self):

return 2 * self.x + 3 * self.y

This time, we also had to redefine the perimeter function, as there is a line going down the middle of the shape. Try creating an instance of this class. As a helpful hint, the idle command line starts where your code ends - so typing a line of code is like adding that line to the end of the program you have written.

Pointers and Dictionaries of Classes

Thinking back, when you say that one variable equals another, e.g. variable2 = variable1, the variable on the left-hand side of the equal-sign takes on the value of the variable on the right. With class instances, this happens a little differently - the name on the left becomes the class instance on the right. So in instance2 = instance1, instance2 is 'pointing' to instance1 - there are two names given to the one class instance, and you can access the class instance via either name.

In other languages, you do things like this using pointers, however in python this all happens behind the scenes.

The final thing that we will cover is dictionaries of classes. Keeping in mind what we have just learnt about pointers, we can assign an instance of a class to an entry in a list or dictionary. This allows for virtually any amount of class instances to exist when our program is run. Lets have a look at the example below, and see how it describes what I am talking about:

Code Example 9 - Dictionaries of Classes

# Again, assume the definitions on Shape,

# Square and DoubleSquare have been run.

# First, create a dictionary:

dictionary = {}

# Then, create some instances of classes in the dictionary:

dictionary["DoubleSquare 1"] = DoubleSquare(5)

dictionary["long rectangle"] = Shape(600,45)

#You can now use them like a normal class:

print dictionary["long rectangle"].area()

dictionary["DoubleSquare 1"].authorName("The Gingerbread Man")

print dictionary["DoubleSquare 1"].author

As you see, we simply replaced our boring old name on the left-hand side with an exciting, new, dynamic, dictionary entry. Pretty cool, eh?

Conclusion

And that is the lesson on classes! You won't believe how long it took me to write this in a clear-cut manner, and I am still not completely satisfied! I have already gone through and rewritten half of this lesson once, and if you're still confused, I'll probably go through it again. I've probably confused some of you with my own confusion on this topic, but remember - it is not something's name that is important, but what it does (this doesn't work in a social setting, believe me... ;)).

Thanks to all,

sthurlow.com

Modules

Introduction

Last lesson we covered the killer topic of Classes. As you can remember, classes are neat combinations of variables and functions in a nice, neat package. Programming lingo calls this feature encapsulation, but reguardless of what it is called, it's a really cool feature for keeping things together so the code can be used in many instances in lots of places. Of course, you've got to ask, "how do I get my classes to many places, in many programs?". The answer is to put them into a module, to be imported into other programs.

Module? What's a Module?

A module is a python file that (generally) has only defenitions of variables, functions, and classes. For example, a module might look like this:

Code Example 1 - moduletest.py

### EXAMPLE PYTHON MODULE

# Define some variables:

numberone = 1

ageofqueen = 78

# define some functions

def printhello():

print "hello"

def timesfour(input):

print input * 4

# define a class

class Piano:

def __init__(self):

self.type = raw_input("What type of piano? ")

self.height = raw_input("What height (in feet)? ")

self.price = raw_input("How much did it cost? ")

self.age = raw_input("How old is it (in years)? ")

def printdetails(self):

print "This piano is a/an " + self.height + " foot",

print self.type, "piano, " + self.age, "years old and costing\

" + self.price + " dollars."

As you see, a module looks pretty much like your normal python program.

So what do we do with a module? We import bits of it (or all of it) into other programs.

To import all the variables, functions and classes from moduletest.py into another program you are writing, we use the import operator. For example, to import moduletest.py into your main program, you would have this:

Code Example 2 - mainprogram.py

### mainprogam.py

### IMPORTS ANOTHER MODULE

import moduletest

This assumes that the module is in the same directory as mainprogram.py, or is a default module that comes with python. You leave out the '.py' at the end of the file - it is ignored. You normally put all import statements at the beginning of the python file, but technically they can be anywhere. In order to use the items in the module in your main program, you use the following:

Code Example 3 - mainprogram.py continued

### USING AN IMPORTED MODULE

# Use the form modulename.itemname

# Examples:

print moduletest.ageofqueen

cfcpiano = moduletest.Piano()

cfcpiano.printdetails()

As you see, the modules that you import act very much like the classes we looked at last lesson - anything inside them must be preceeded with modulename. for it to work.

More module thingummyjigs (in lack of a better title)

Wish you could get rid of the modulename. part that you have to put before every item you use from a module? No? Never? Well, I'll teach it you anyway.

One way to avoid this hassle is to import only the wanted objects from the module. To do this, you use the from operator. You use it in the form of from modulename import itemname. Here is an example:

Code Example 4 - importing individual objects

### IMPORT ITEMS DIRECTLY INTO YOUR PROGRAM

# import them

from moduletest import ageofqueen

from moduletest import printhello

# now try using them

print ageofqueen

printhello()

What is the point of this? Well, maybe you could use it to make your code a little more readable. If we get into heaps of modules inside modules, it could also remove that extra layer of crypticness.

If you wanted to, you could import everything from a module is this way by using from modulename import *. Of course, this can be troublesome if there are objects in your program with the same name as some items in the module. With large modules, this can easily happen, and can cause many a headache. A better way to do this would be to import a module in the normal way (without the from operator) and then assign items to a local name:

Code Example 5 - mainprogram.py continued

### ASSIGNING ITEMS TO A LOCAL NAME

# Assigning to a local name

timesfour = moduletest.timesfour

# Using the local name

print timesfour(565)

This way, you can remove some crypticness, AND have all of the items from a certain module.

Conclusion

That's it! A very simple lesson, but now you can organise your programs very neatly. In fact, now it is increadibly easy to make progams that can grow in complexity without ending up with one cryptic file that is full of bugs.

Modules are great for importing code. Next lesson, we learn about file input and output, and the saving of information inside classes, to be retrieved later. Will be great! But until then...

Thanks to all,

sthurlow.com

File I/O

Introduction

Last lesson we learnt how to load external code into our program. Without any introduction (like what I usually have), let's delve into file input and output with normal text files, and later the saving and restoring of instances of classes. (Wow, our lingo power has improved greatly!)

Opening a file

To open a text file you use, well, the open() function. Seems sensible. You pass certain parameters to open() to tell it in which way the file should be opened - 'r' for read only, 'w' for writing only (if there is an old file, it will be written over), 'a' for appending (adding things on to the end of the file) and 'r+' for both reading and writing. But less talk, lets open a file for reading (you can do this in your python idle mode). Open a normal text file. We will then print out what we read inside the file:

Code Example 1 - Opening a file

openfile = open('pathtofile', 'r')

openfile.read()

That was interesting. You'll notice a lot of '

' symbols. These represent newlines (where you pressed enter to start a new line). The text is completely unformatted, but if you were to pass the output of openfile.read() to print (by typing print openfile.read()) it would be nicely formatted.

Seek and You Shall Find

Did you try typing in print openfile.read()? Did it fail? It likely did, and reason is because the 'cursor' has changed it's place. Cursor? What cursor? Well, a cursor that you really cannot see, but still a cursor. This invisible cursor tells the read function (and many other I/O functions) where to start from. To set where the cursor is, you use the seek() function. It is used in the form seek(offset, whence).

whence is optional, and determines where to seek from. If whence is 0, the bytes/letters are counted from the beginning. If it is 1, the bytes are counted from the current cursor position. If it is 2, then the bytes are counted from the end of the file. If nothing is put there, 0 is assumed.

offset decribes how far from whence that the cursor moves. for example:

* openfile.seek(45,0) would move the cursor to 45 bytes/letters after the beginning of the file.

* openfile.seek(10,1) would move the cursor to 10 bytes/letters after the current cursor position.

* openfile.seek(-77,2) would move the cursor to 77 bytes/letters before the end of the file (notice the - before the 77)

Try it out now. Use openfile.seek() to go to any spot in the file and then try typing print openfile.read(). It will print from the spot you seeked to. But realise that openfile.read() moves the cursor to the end of the file - you will have to seek again.

Other I/O Functions

There are many other functions that help you with dealing with files. They have many uses that empower you to do more, and make the things you can do easier. Let's have a look at tell(), readline(), readlines(), write() and close().

tell() returns where the cursor is in the file. It has no parameters, just type it in (like what the example below will show). This is infinitely useful, for knowing what you are refering to, where it is, and simple control of the cursor. To use it, type fileobjectname.tell() - where fileobjectname is the name of the file object you created when you opened the file (in openfile = open('pathtofile', 'r') the file object name is openfile).

readline() reads from where the cursor is till the end of the line. Remember that the end of the line isn't the edge of your screen - the line ends when you press enter to create a new line. This is useful for things like reading a log of events, or going through something progressively to process it. There are no parameters you have to pass to readline(), though you can optionally tell it the maximum number of bytes/letters to read by putting a number in the brackets. Use it with fileobjectname.readline().

readlines() is much like readline(), however readlines() reads all the lines from the cursor onwards, and returns a list, with each list element holding a line of code. Use it with fileobjectname.readlines(). For example, if you had the text file:

Code Example 2 - example text file

Line 1

Line 3

Line 4

Line 6

then the returned list from readlines() would be:

Table 1 - resulting list from readlines

Index Value

0 'Line 1'

1 ''

2 'Line 3'

3 'Line 4'

4 ''

5 'Line 6'

The write() function, writes to the file. How did you guess??? It writes from where the cursor is, and overwrites text in front of it - like in MS Word, where you press 'insert' and it writes over the top of old text. To utilise this most purposeful function, put a string between the brackets to write e.g. fileobjectname.write('this is a string').

close, you may figure, closes the file so that you can no longer read or write to it until you reopen in again. Simple enough. To use, you would write fileobjectname.close(). Simple!

In Python idle mode, open up a test file (or create a new one...) and play around with these functions. You can do some simple (and very inconvenient) text editing.

Mmm, Pickles

Pickles, in Python, are to be eaten. Their flavour is just to good to let programmers leave them in the fridge.

Ok, just joking there. Pickles, in Python, are objects saved to a file. An object in this case could be a variables, instance of a class, or a list, dictionary, or tuple. Other things can also be pickled, but with limits. The object can then be restored, or unpickled, later on. In other words, you are 'saving' your objects.

So how do we pickle? With the dump() function, which is inside the pickle module - so at the beginning of your program you will have to write import pickle. Simple enough? Then open an empty file, and use pickle.dump() to drop the object into that file. Let's try that:

Code Example 3 - pickletest.py

### pickletest.py

### PICKLE AN OBJECT

# import the pickle module

import pickle

# lets create something to be pickled

# How about a list?

picklelist = ['one',2,'three','four',5,'can you count?']

# now create a file

# replace filename with the file you want to create

file = open('filename', 'w')

# now let's pickle picklelist

pickle.dump(picklelist,file)

# close the file, and your pickling is complete

file.close()

The code to do this is laid out like pickle.load(object_to_pickle, file_object) where:

* object_to_pickle is the object you want to pickle (i.e. save it to file)

* file_object is the file object you want to write to (in this case, the file object is 'file')

After you close the file, open it in notepad and look at what you see. Along with some other gibblygook, you will see bits of the list we created.

Now to re-open, or unpickle, your file. to use this, we would use pickle.load():

Code Example 4 - unpickletest.py

### unpickletest.py

### unpickle file

# import the pickle module

import pickle

# now open a file for reading

# replace filename with the path to the file you created in pickletest.py

unpicklefile = open('filename', 'r')

# now load the list that we pickled into a new object

unpickledlist = pickle.load(unpicklefile)

# close the file, just for safety

unpicklefile.close()

# Try out using the list

for item in unpickledlist:

print item

Nifty, eh?

Of course, the limitation above is that we can only put in one object to a file. We could get around this by putting lots of picklable objects in a list or dictionary, and then pickling that list or dictionary. This is the quickest and easiest way, but you can do some pretty advanced stuff if you have advanced knowledge of pickle.

Which we won't cover.

Conclusion

Which ends this lesson.

Thanks to all,

sthurlow.com

Exception Handling

Introduction

If you haven't seen them before, you're not trying hard enough. What are they? Errors. Exceptions. Problems. Know what I'm talking about? I got it with this program:

Code Example 1 - buggy program

def menu(list, question):

for entry in list:

print 1 + list.index(entry),

print ") " + entry

return input(question) - 1

# running the function

# remember what the backslash does

answer = menu(['A','B','C','D','E','F','H','I'],\

'Which letter is your favourite? ')

print 'You picked answer ' + (answer + 1)

This is just an example of the menu program we made earlier. Appears perfectly fine to me. At least until when I first tried it. Run the program, and what happens?

Bugs - Human Errors

The most common problems with your code are of your own doing. Sad, but true. What do we see when we try to run our crippled program?

Code Example 2 - error message

Traceback (most recent call last):

File "/home/steven/errortest.py", line 8, in -toplevel-

answer = menu(< I'll snip it here >)

File "/home/steven/errortest.py", line 6, in menu

return raw_input(question) - 1

TypeError: unsupported operand type(s) for -: 'str' and 'int'

Say what? What python is trying to tell you (but struggling to find a good word for it) is that you can't join a string of letters and a number into one string of text. Let's go through the error message and have a look at how it tells us that:

* File "/home/steven/errortest.py", line 8, in -toplevel- tells us a couple of things. File "/home/steven/errortest.py" tells us which file the error occured in. This is useful if you use lots of modules that refer to each other. line 8, in -toplevel- tells us that it is in line # 8 of the file, and in the top level (that is, no indentation).

* answer = menu(['A','B','C','D','E','F','H','I'],'Which letter is your favourite? ') duplicates the code where the error is.

* Since this line calls a function, the next two lines describe where in the function the error occured.

* TypeError: unsupported operand type(s) for -: 'str' and 'int' tells you the error. In this case, it is a 'TypeError', where you tried to subtract incompatible variables.

There are muliple file and code listings for a single error, because the error occured with the interaction of two lines of code (e.g. when using a function, the error occured on the line where the function was called, AND the line in the function where things went wrong).

Now that we know what the problem is, how do we fix it. Well, the error message has isolated where the problem is, so we'll only concentrate on that bit of code.

Code Example 3 - calling the menu function

answer = menu(['A','B','C','D','E','F','H','I'],\

'Which letter is your favourite? ')

This is a call to a function. The error occured in the function in the following line

Code Example 4 - Where it went wrong

return raw_input(question) - 1

raw_input always returns a string, hence our problem. Let's change it to input(), which, when you type in a number, it returns a number:

Code Example 5 - Fixing it

return input(question) - 1

Bug fixed!

Exceptions - Limitations of the Code

OK, the program works when you do something normal. But what if you try something weird? Type in a letter (lets say, 'm') instead of a number? Whoops!

Code Example 6 - Another error message

Traceback (most recent call last):

File "/home/steven/errortest.py", line 8, in -toplevel-

answer = menu(< I'll snip it here >)

File "/home/steven/errortest.py", line 6, in menu

return input(question) - 1

File "", line 0, in -toplevel-

NameError: name 'g' is not defined

What is this telling us? There are two code listings - one in line 8, and the other in line 6. What this is telling us is that when we called the menu function in line 8, an error occured in line 6 (where we take away 1). This makes sense if you know what the input() function does - I did a bit of reading and testing, and realised that if you type in a letter or word, it will assume that you are mentioning a variable! so in line 6, we are trying to take 1 away from the variable 'm', which doesn't exist.

Have no clue on how to fix this? One of the best and easiest ways is to use the try and except operators.

Here is an example of try being used in a program:

Code Example 7 - The try operator

try:

function(world,parameters)

except:

print world.errormsg

This is an example of a really messy bit of code that I was trying to fix. First, the code under try: is run. If there is an error, the compiler jumps to the except section and prints world.errormsg. The program doesn't stop right there and crash, it runs the code under except: then continues on.

Lets try that where the error occured in our code (line 6). The menu function now is:

Code Example 8 - testing our fix

def menu(list, question):

for entry in list:

print 1 + list.index(entry),

print ") " + entry

try:

return input(question) - 1

except NameError:

print "Enter a correct number"

Try entering a letter when you're asked for a number and see what happens. Dang. We fixed one problem, but now it has caused another problem furthur down the track. This happens all the time. (Sometimes you end up going around in circles, because your code is an absolute mess). Let's have a look at the error:

Code Example 9 - Yet another error message

Traceback (most recent call last):

File "/home/steven/errortest.py", line 12, in -toplevel-

print 'You picked answer', (answer + 1)

TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'

What has happened this time is that the menu function has returned no value - it only printed an error message. When, at the end of the program, we try to print the returned value plus 1, what is the returned value? There is no returned value? So what is 1 + ... well, we have no clue what we are adding 1 to!

We could just return any old number, but that would be lying. What we really should to is rewrite the program to cope with this exception. With what? try and except!

Code Example 10 - yet another solution

# from when we finish defining the function

answer = menu(['A','B','C','D','E','F','H','I'],\

'Which letter is your favourite? ')

try:

print 'You picked answer', (answer + 1)

# you can put stuff after a comma in the 'print' statement,

# and it will continue as if you had typed in 'print' again

except:

print '

incorrect answer.'

# the '

' is for formatting reasons. Try without it and see.

Problem solved again.

Endless Errors

The approach that we used above is not recomended. Why? Because apart from the error that we know can happen, except: catches every other error too. What if this means we never see an error that could cause problems down the track? If except: catches every error under the sun, we have no hope of controlling what errors we deal with, and the other ones that we want to see, because so far we haven't dealt with them. We also have little hope of dealing with more than one type of error in the same block of code. What should one do, when all is hopeless? Here is an example of code with such a situation:

Code Example 11 - The Problem We Face

print 'Subtraction program, v0.0.1 (beta)'

a = input('Enter a number to subtract from > ')

b = input('Enter the number to subtract > ')

print a - b

Ok, you enter your two numbers and it works. Enter a letter, and it gives you a NameError. Lets rewrite the code to deal with a NameError only. We'll put the program in a loop, so it restarts if an error occurs (using continue, which starts the loop from the top again, and break, which leaves the loop):

Code Example 12 - Dealing With NameError

print 'Subtraction program, v0.0.2 (beta)'

loop = 1

while loop == 1:

try:

a = input('Enter a number to subtract from > ')

b = input('Enter the number to subtract > ')

except NameError:

print "

You cannot subtract a letter"

continue

print a - b

try:

loop = input('Press 1 to try again > ')

except NameError:

loop = 0

Here, we restarted the loop if you typed in something wrong. In line 12 we assumed you wanted to quit the program if you didn't press 1, so we quit the program.

But there are still problems. If we leave something blank, or type in an unusual character like ! or ;, the program gives us a SyntaxError. Lets deal with this. When we are asking for the numbers to subtract, we will give a different error message. When we ask to press 1, we will again assume the user wants to quit.

Code Example 13 - Now, Dealing With SyntaxError

print 'Subtraction program, v0.0.3 (beta)'

loop = 1

while loop == 1:

try:

a = input('Enter a number to subtract from > ')

b = input('Enter the number to subtract > ')

except NameError:

print "

You cannot subtract a letter"

continue

except SyntaxError:

print "

Please enter a number only."

continue

print a - b

try:

loop = input('Press 1 to try again > ')

except (NameError,SyntaxError):

loop = 0

As you can see, you can have multiple except uses, each dealing with a different problem. You can also have one except to deal with multiple exceptions, by putting them inside parentheses and seperating them with commas.

Now we have a program that is very difficult, to crash by an end user. As a final challenge, see if you can crash it. There is one way I have thought of - if you read the chapter on Human Error carefully, you might know what it is.

Conclusion, Sweet Conclusion

There you go! The final lesson on python! Finally we are finished. That is, unless you want to also know XML. Civilization IV and XML don't really interact directly, so we won't worry about that for the moment - plus, some great and very helpful posters on the CFC Civ4 C&C Forum (take that!) have already helped you out there. There will be an introduction or two to Civilization IV python specifics, and then you should be on your way. See you there!

For those of you not doing this for the gaming, thanks for reading. May your pythoning be forever successful, and if you need to find anything out, try the Python home page for an exhaustive resource on everything from 2D game programming, to multithreading, to XML parsing. There really is a huge amount of stuff you can now do, and the best way to learn, is to go and find out.

Thanks to all,

sthurlow.com

Continue Reading

You'll Also Like

7.8K 49 2
In this book, you'll get a behind the scenes look at how your favorite characters were born, my creative process, and the dirty details never before...
Wattpad App - Unlock exclusive features