Python (civ4 scripting language) tutorial thread

LESSON 5:
Oh, so functional!

Last lesson I said that we would delve into purposefull programming. That involves user input, and user input requires a thing called functions.

What are functions? Well, in effect, functions are little self-contained programs that perform a specific task, which you can incorporate into your own, larger programs. This saves you the time and effort of having to retell the computer what to do every time it does a common task, for example getting the user to type something in.

A function is very simple. You give it some input, and it will become a value, as an output. Don't understand? Here is the general form that a function takes:

Code:
[i]function_name[/i]([i]parameters[/i])

See? Easy.
Function_name identifies which function it is you want to use. For example, the function raw_input, which will be the first function that we will use.
Parameters tells the function what to do. for example, if a function multiplied any given number by five, the stuff in parameters tells the function which number it should multiply by five. Put the number 70 into parameters, and the function will do 70 x 5.

Well, that's all well and good that the program can multiply a number by five, but what does it have to show for it? A warm fuzzy feeling? Your program needs to see the results of what happened, to see what 70 x 5 is, or to see if there is a problem somewhere (like you gave it a letter instead of a number). So how does a function show what is does?

Well, in effect, when a computer runs a function, it doesn't actually see the function name, but the result of what the function did. Lets call this program that multiplied any number by five, multiply(). You put the number you want multiplied in the brackets. So if you typed this:
Code:
a = multiply(70)
The computer would actually see this:
Code:
a = 350
(P.S. don't bother typing in this code).
The function pretty much turned itself into a number, based on what parameters it was given.

Now let's try this with a real function, and see what it does. The function is called raw_input, and asks the user to type in something. It then turns it into a string of text. Try the code below:
Code:
# this line makes 'a' equal whatever you type in
a = raw_input("Type in something, and it will be repeated on screen:")

# this line prints what 'a' is now worth
print a

Say in the above program, you typed in 'hello' when it asked you to type something in. To the computer, this program would look like this:
Code:
a = "hello"
print "hello"
Remember, a variable is just a stored value. To the computer, the variable 'a' doesn't look like 'a' - it looks like the value that is stored inside it. Functions are similar - to the computer, they look like the value of what they give in return of running.

Lets write another program, that will act as a calculator. This time it will do something more adventerous than what we have done before. There will be a menu, that will ask you whether you want to multiply two numbers together, add two numbers together, divide one number by another, or subtract one number from another. Only problem - the raw_input function only turns what you type in into text - we want the number 1, not the letter 1 (and yes, in python, there is a difference.).

Luckily, somebody wrote the function input, which gives what you typed in, to the program - but this time, it puts it in as a number. If you type an integer, what comes out of input is an integer. And if you put that integer into a variable, the variable will be an integer - type variable, which means you can add and subtract, etc.

Now, lets design this calculator properly. We want a menu that is returned to every time you finish adding, subtracting, etc. In other words, to loop (HINT!!!) while (BIG HINT!!!) you tell it the program should still run.

We want it to do an option in the menu if you type in that number. That involves you typing in a number (a.k.a input) and an if loop.

Lets write it out in understandable English first:
Code:
START PROGRAM
print opening message

while we let the program run, do this:
    #Print what options you have
    print Option 1 - add
    print Option 2 - subtract
    print Option 3 - multiply
    print Option 4 - divide
    print Option 5 - quit program
    
    ask for which option is is you want
    if it is option 1:
        ask for first number
	ask for second number
	add them together
	print the result onscreen
    if it is option 2:
        ask for first number
	ask for second number
	subtract one from the other
	print the result onscreen
    if it is option 3:
        ask for first number
	ask for second number
	multiply!
	print the result onscreen
    if it is option 4:
        ask for first number
	ask for second number
	divide one by the other
	print the result onscreen
    if it is option 5:
        tell the loop to stop looping
	
Print onscreen a goodbye message
END PROGRAM

Lets put this in something that python can understand:
Code:
#calculator program

#this variable tells the loop whether it should loop or not.
# 1 means loop. anything else means don't loop.

loop = 1

#this variable holds the user's choice in the menu:

choice = 0

while loop == 1:
    #print what options you have
    print "Welcome to calculator.py"
    print "your options are:"
    print " "
    print "1) Addition"
    print "2) Subtraction"
    print "3) Multiplication"
    print "4) Division"
    print "5) Quit calculator.py"
    print " "
    choice = input("Choose your option: ")
    if choice == 1:
        add1 = input("Add this: ")
	add2 = input("to this: ")
	print add1, "+", add2, "=", add1 + add2
    elif choice == 2:
        sub2 = input("Subtract this: ")
	sub1 = input("from this: ")
	print sub1, "-", sub2, "=", sub1 - sub2
    elif choice == 3:
        mul1 = input("Multiply this: ")
	mul2 = input("with this: ")
	print mul1, "*", mul2, "=", mul1 * mul2
    elif choice == 4:
        div1 = input("Divide this: ")
	div2 = input("by this: ")
	print div1, "/", div2, "=", div1 / div2
    elif choice == 5:
        loop = 0
	
print "Thankyou for using calculator.py!"
Wow! That is an impressive program! Paste it into python IDLE, save it as 'calculator,py' and run it. Play around with it - try all options, entering in integers (numbers without decimal points), and numbers with stuff after the decimal point (known in programming as a floating point). Try typing in text, and see how the program chucks a minor fit, and stops running. I'll explain that later, if you ask me to.

Well, it is all well and good that you can use other people's functions, but what if you want to write your own functions, to save time, and maybe use them in other programs? This is where the def operator comes in. (An operator is just something that tells python what to do, e.g. the '+' operator tells python to add things, the 'if' operator tells python to do something if conditions are met.)

This is how the 'def' operator works:
Code:
def [i]function_name[/i]([i]parameter_1_variable[/i],[i]parameter_2_variable[/i]):
    {this is the code in the function}
    {more code}
    {more code}
    return {text, or number to return to the main program}

{this code isn't in the function}
{because it isn't indented}
#remember to put a colon ":" at the end of the line that starts with 'def'
Functions run completely independent of the main program. Remember when I said that when the computer comes to a function, it doesn't see the function, but a value, that the function returns? Here's the quote:
a variable is just a stored value. To the computer, the variable 'a' doesn't look like 'a' - it looks like the value that is stored inside it. Functions are similar - to the computer, they look like the value of what they give in return of running.
So in this sense, functions aren't really cutting and pasting code in a convenient way. It is more like a miniture program that some parameters are given to - it then runs itself, and then returns a value. Your main program sees only the returned value. If that function flew to the moon and back, and then at the end had
Code:
    return 1
then all your program would see is the number '1', where the name of the function was. It would have no idea what else the program did.

Because it is a seperate program, a function doesn't see any of the variables that are in your main program, and your main program doesn't see any of the variables that are in a function.


For example, here is a function that prints the words "hello" onscreen, and then returns the number '1234' to the main program:
Code:
#Below is the function
def hello():
    print hello
    return 1234
    
#And here is the function being used
print hello()

Think about the last line of code above. What did it do? Type in the program (you can skip the comments), and see what it does. The output looks like this:
Code:
[color=blue]hello
1234[/color]
So what happened?
1) When the line 'print hello' was run, the function 'hello' was executed.
2) The function 'hello' printed "hello" onscreen, then returned the number '1234' back to the main program
3) The main program now sees the line as 'print 1234' and as a result, printed '1234'

That accounts for everything that happened. remember, that the main program had NO IDEA that the words "hello" were printed onscreen. All it saw was '1234', and printed that onscreen.

There is one more thing we will cover in this (monsterly huge) lesson - passing parameters to a function. Remember that calculator program. Did it look a bit messy to you? I think it did, so lets re-write it, with functions.

To design - First we will define all the functions we are going to use with the 'def' operator (still remember what an operator is ;) ).
Then we will then have the main program, with all that messy code replaced with nice functions. This will make it so much easier to look at again in the future.

Code:
#calculator program

#NO CODE IS REALLY RUN HERE, IT IS ONLY TELLING US WHAT WE WILL DO LATER
#Here we will define our functions
#this prints the main menu, and prompts for a choice
def menu():
    #print what options you have
    print "Welcome to calculator.py"
    print "your options are:"
    print " "
    print "1) Addition"
    print "2) Subtraction"
    print "3) Multiplication"
    print "4) Division"
    print "5) Quit calculator.py"
    print " "
    return input ("Choose your option: ")
    
#this adds two numbers given
def add(a,b):
    print a, "+", b, "=", a + b
    
#this subtracts two numbers given
def sub(a,b):
    print b, "-", a, "=", b - a
    
#this multiplies two numbers given
def mul(a,b):
    print a, "*", b, "=", a * b
    
#this divides two numbers given
def div(a,b):
    print a, "/", b, "=", a / b
    
#NOW THE PROGRAM REALLY STARTS, AS CODE IS RUN
loop = 1
choice = 0
while loop == 1:
    choice = menu()
    if choice == 1:
        add(input("Add this: "),input("to this: "))
    elif choice == 2:
        sub(input("Subtract this: "),input("from this: "))
    elif choice == 3:
        mul(input("Multiply this: "),input("by this: "))
    elif choice == 4:
        div(input("Divide this: "),input("by this: "))
    elif choice == 5:
        loop = 0

print "Thankyou for using calculator.py!"
#NOW THE PROGRAM REALLY FINISHES
The initial program had 34 lines of code. The new one actually had 35 lines of code! It is a little longer, but if you look at it the right way, it is actually simpler.

You defined all your functions at the top. This really isn't part of your main program - they are just lots of little programs, that you will call upon later. You could even re-use these in another program if you needed them, and didn't want to tell the computer how to add and subtract again.

If you look at the main part of the program (between the line 'loop = 1' and 'print "Thankyou for..."'), it is only 15 lines of code. That means that if you wanted to write this program differently, you would only have to write 15 or so lines, as opposed to the 34 lines you would normally have to without functions.

Finally, as a bit of an interlude, I will explain what the line 'add(input("Add this: "),input("to this: "))' means.
I wanted to fit everything onto one line, with as few variables as possible. Remember what functions look like to the main program? Whatever value they return. If the numbers you gave were 2 and 30, the main program would see this:
Code:
        add(2,30)

The add program would then run. The add program has no 'return' operator - it doesn't return anything to the main program. It simply multiplies two numbers and prints them onscreen, and the main program doesn't see anything of it.

Instead of '(input("Add this: "),input("to this: "))' as the parameters for the add program you could have variables. E.g.
Code:
num1 = 45
num2 = 7
add(num1,num2)
You could even put the numbers straight into the function:
Code:
add(45,7)
This is because the only thing the function sees are the values that are passed on as parameters. Those values are put into the variables that are mentioned when 'add' is defined (the line 'def add(a,b)' ). The function then uses those parameters to do it's job.

In short:
*) the only thing functions see of the main program is the parameters.
*) the only thing the main program seens of functions is the returned values.

WHOA!!!! WHAT A KILLER LESSON!!! But we got through it, and I made minimal typos. Great!

I haven't decided what will happen in lesson 6. All I can say is I am having a BIG breather, because this lesson took me many hours to write.

Thanks to all,
Gingerbread Man.
 
croxis said:
done. gbm have you thought of just taking what is used in th epython documentation and just doing minor edits ot make it understabable?
I'm already doing something along those lines. I've been drawing information from a beginner's guide to python, and re-organising the sections in more complete lessons.

If anybody has any pointers to anything that could do with improvement in the lessons, tell me. That can be anything from a confusing sentence in one of the lessons, to the general structure of my writing - remember, you're getting out what you put in.

I've just gone through a major system re-install (note - installing Fedora three times in two days is a nuisance, to say the least), but hopefully I should find some material for next lesson - hopefully, do lists and arrays, and then move on to some interesting stuff. I'll check out what else we have to learn before straying into graphical stuff, and AI programming. At the moment I'm working on a lesson plan to get us there. Hang tight, and it will turn up 'soon'.
 
I forgot also...
I am done with lesson 5
thanks
 
I'm up to date.

Thanks for your efforts, GBM, it helps out quite a few people who certainly appreciate your work (even if you're also benefitting from it ;)).
 
Thanks, Trip. Hopefully it will become a useful tutorial when civIV comes out. I'll probably rewrite the tutorial when it does come out, and host it on my website.

BTW, what would you recommend for the next couple of lessons? At the moment I'm doing tuples, lists and dictionaries. I'll cover the for loop briefly after that, then what? I'm open to any suggestions.

EDIT: Hopefully the next lesson will be up in 24hrs. I think I've finally found a way to present it clearly.
 
I would recommend doing stuff with classes and linking together different files. Then maybe some input stuff (after all, if CIV is going to use Python and XML, there has to be a way for the Python code to read what is stored in the XML).
 
well, I wanty to write a python plugin for x-chat which looks at a directory full of different text files, then when someoen types in the name of one of those texts files it will respond with a random quote from that text file. While this has nothing to do with civ it sure would be nice to have ;)
 
LESSON 6:
Tuples, Lists, and Dictionaries

Your brain still hurting from the last lesson? Never worry, this one will require a little less thought. We're going back to something simple - variables - but a little more in depth.

Think about it - variables store one bit of information. They may regurgitate (just not on the carpet...) that information at any point, and their bit of information can be changed at any time Variables are great at what they do - storing a piece of information that may change over time.

But what if you need to store a long list of information, which doesn't change over time? Say, for example, the names of the months of the year.

Or maybe a long list of information, that does change over time? Say, for example, the names of all your cats. You might get new cats, some may die, some may become your dinner (we should trade recipies!).

What about a phone book? For that you need to do a bit of referencing - you would have a list of names, and attached to each of those names, a phone number. How would you do that?

For these three problems, Python uses three different solutions - Tuples, lists, and dictionaries.

Lists are what they seem - a list of values. Each one of them is numbered, starting from zero - the first one is numbered zero, the second 1, the third 2, etc. You can remove values from the list, and add new values to the end. E.g. Your many cats' names.

Tuples are just like lists, but you can't change their values. The values that you give it first up, are the values that you are stuck with for the rest of the program. Again, each value is numbered starting from zero, for easy reference. E.g. the names of the months of the year.

Dictionaries are similar to what their name suggests - a dictionary. In a dictionary, you have an 'index' of words, and for each of them a definition. In python, the word is called a 'key', and the definition a 'value'. The values in a dictionary aren't numbered - they aren't in any specific order, either - the key does the same thing. You can add, remove, and modify the values in dictionaries. E.g. A telephone book.

Well, now we know what they do, lets see how to use them.

TUPLES

Tuples are pretty easy to make. You give your tuple a name, then after that the list of values it will carry. For example, the months of the year:
Code:
months = ('January','February','March','April','May','June',\
'July','August','September','October','November','December')
Note that the '\' thingy at the end of the first line carries over that line of code to the next line. It is usefull way of making big lines more readable.

Technically you don't have to put those parentheses there (the '(' and ')' thingies) but it stops python from getting things confused.

You may have spaces after the commas if you feel it necessary - it doesn't really matter.

Python then organises those values in a handy, numbered index - starting from zero, in the order that you entered them in. It would be organised like this:
Code:
Index  Value
 0     January
 1     February
 2     March
 3     April
 4     May
 5     June
 6     July
 7     August
 8     September
 9     October
 10    November
 11    December
Knowing that, it should be pretty easy to recall values from the tuple. They are just like numbered variables. Here is an example:

Code:
#Telling the computer the names of the months:
months = ('January','February','March','April','May','June',\
'July','August','September','October','November','December')

#printing January onscreen:
print months[0]

#printing October:
print months[9]

#create a variable, and put 'August' in it
x = months[7]
print x

#put the months of (southern hemisphere) winter in another variable:
winter = months[5:8]
print winter
And that is tuples! Really easy...

LISTS

Lists are extremely similar to tuples. Lists are modifiable (or 'mutable', as a programmer may say), so their values can be changed. Most of the time we use lists, not tuples.

Lists are defined very similarly to tuples. Say you have FIVE cats, called Tom, Snappy, Kitty, Jessie and Chester. To put them in a list, you would do this:
Code:
cats = ['Tom', 'Snappy', 'Kitty', 'Jessie', 'Chester']
As you see, the code is exactly the same as a tuple, EXCEPT that all the values are put between square brackets, not parentheses. Again, you don't have to have spaces after the comma.

You recall values from lists exactly the same as you do with tuples. For example, to print the name of your 3rd cat you would do this:
Code:
print cats[2]
You can also recall a range of examples, like above, for example - cats[0:2] would recall your 1st and 2nd cats.

Where lists come into their own is how they can be modified. To add a value to a list, you use the 'append()' function. Let's say you got a new cat called Catherine. To add her to the list you'd do this:
Code:
cats.append('Catherine')
That's a little weird, isn't it? I'll explain. That function is in a funny spot - after a period (the '.' kind of period, not otherwise), after the list name. You'll get to see those things more in a later lesson. For the meanwhile, this is the form of the function that adds a new value to a list:
Code:
#add a new value to the end of a list:
[i]list_name[/i].append([u]value-to-add[/u])

#e.g. to add the number 5038 to the list 'numbers':
numbers.append(5038)
Clears things up? Good!

Now to a sad situation - Snappy was shot by a neighbour, and eaten for their dinner (good on 'em!). You need to remove him (or her) from the list. Removing that sorry cat is an easy task, thankfully, so you have to wallow in sadness for as short a time as possible:
Code:
#Remove your 2nd cat, Snappy. Woe is you.
del cats[1]
You've just removed the 2nd cat in your list - poor old Snappy.

And with that morbid message, lets move on to...

DICTIONARIES

Ok, so there is more to life than the names of your cats. You need to call your sister, mother, son, the fruit man, and anyone else who needs to know that their favourite cat is dead. For that you need a telephone book.

Now, the lists we've used above aren't really suitable for a telephone book. You need to know a number based on someone's name - not the other way around. In the examples of months and cats, we gave the computer a number, and it gave us a name. This time we want to give the computer a name, and it give us a number. For this we need Dictionaries.

So how do we make a dictionary? Put away your binding equipment, it isn't that advanced.

Remember, dictionaries have keys, and values. In a phone book, you have people's names, then their numbers. See a similarity?

When you initially create a dictionary, it is very much like making a tuple or list. Tuples have ( and ) things, lists have [ and ] things. Guess what! dictionaries have { and } things - curly braces. Here is an example below, showing a dictionary with four phone numbers in it:
Code:
#Make the phone book:
phonebook = {'Andrew Parson':8806336, 'Emily Everett':6784346, 'Peter Power':7658344, 'Lewis Lame':1122345}

#Print out Lewis Lame's number:
print phonebook['Lewis Lame']
the program would then print Lewis Lame's number onscreen. Notice how instead of identifying the value by a number, like in the cats and months examples, we identify the value, using another value - in this case the person's name.

Ok, you've created a new phone book. Now you want to add new numbers to the book. What do you do? A very simple line of code:
Code:
#Add the person 'Gingerbread Man' to the phonebook:
phonebook['Gingerbread Man'] = 1234567
#(Didn't think I would give you my real number now, would I?)
All that line is saying is that there is a person called Gingerbread Man in the phone book, and his number is 1234567. In other words - the key is 'Gingerbread Man', and the value is 1234567.

You delete entries in a dictionary just like in a list. Let's say Andrew Parson is your neighbour, and shot your cat. You never want to talk to him again, and therefore don't need his number. Just like in any other list, you'd do this:
Code:
del phonebook['Andrew Parson']
Again, very easy.

remember that append function that we used with the list? Well, there are quite a few of those that can be used with dictionaries. Below, I will write you a program, and it will incorporate some of those functions in. It will have comments along the way explaining what it does.

Type this program into Python IDLE (you can skip the comments). Experiment as much as you like with it. Type it where you see the lines beginning with >>>
Code:
#A few examples of a dictionary

#First we define the dictionary
#it will have nothing in it this time
ages = {}

#Add a couple of names to the dictionary
ages['Sue'] = 23
ages['Peter'] = 19
ages['Andrew'] = 78
ages['Karren'] = 45

#Use the function has_key() - 
#This function takes this form:
#[i]function_name[/i].has_key([u]key-name[/u])
#It returns TRUE if the dictionary has [u]key-name[/u] in it
#but returns FALSE if it doesn't
#remember - this is how 'if' statements work - they run if something is true
#and they don't when something is false.
if ages.has_key('Sue'):
    print "Sue is in the dictionary. She is", ages['Sue'], "years old"
else:
    print "Sue is not in the dictionary"

#Use the function keys() - 
#This function returns a list of all the names of the keys.
#E.g.
print "The following people are in the dictionary:"
print ages.keys()

#You could use this function to put all the key names in a list:
keys = ages.keys()

#You can also get a list of all the values in a dictionary.
#You use the values() function:
print "People are aged the following:", ages.values()

#Put it in a list:
values = ages.values()

#You can sort lists, with the sort() function
#It will sort all values in a list alphabetically, numerically, etc...
#You can't sort dictionaries - they are in no particular order
print keys
keys.sort()
print keys

print values
values.sort()
print values

#You can find the number of entries with the len() function:
print "The dictionary has", len(ages), "entries in it"
There are many other functions you can use to work with lists and dictionaries - too many to go through right now. We'll leave the lesson at this point - you have learnt enough for one lesson.

I'll post a lesson plan briefly. Please comment on it when it appears.
Thanks to all,
Gingerbread Man.
 
Top Bottom