Chapter 2. Our first Python statements
In the previous chapter, we have some code in a sentence jumped straight into the development of our first project – an animated game. Along the way, we encountered a series of Python statements. We shall now look at these statements in more detail and experiment with them a bit more, before we go on with completing our game.
The list of Python constructs we have encountered so far is quite long already. It includes function calls, parameters, objects, method calls, variables, assignment and if-statements.
You will have got a sense of what these statements do, and what they are there for. You will not, however, understand fully how any of them work yet. Don’t worry – that is perfectly okay. We will come back to talk more about each of these constructs and experiment with them, and you will gain a full understanding over time.
We will now go through this list and investigate each of these constructs a bit more, so that we can become comfortable with working with these language features before we start looking at new functionality. Let’s start with one of the most fundamental Python constructs: a function call.
2.1. Function calls
We have seen function calls a couple of times now. For example, we have seen the call
and the call
In each case, we call, or invoke, an existing function to get it to do some task for us (setting the background colour, in this case, or setting the pace of the loop.)
In general, a function call always has the format
function-name ( parameters )
The function name specifies the name of the function we wish to call, and the parameters provide some more information to execute the call. Both functions above have one parameter, but a function can have more than one parameter, or none at all, indicating that no further information is required. If a function does not have any parameters, then we still write the parentheses. We just write nothing in between. For example
calls a function called "stop" that has no parameters. It is the presence of the round brackets (also known as parentheses) that identifies this statement as a function call.
To practice with function calls, we will now use another project: fireworks.
Exercise 2.1 Open the fireworks project from the "Chapter02" folder of the book projects. Run the project. What do you observe?
If you have completed the exercise above, you will have seen that this project includes some code, but does very little when we run it. In fact, you have to look very carefully to notice any effect at all: It sets the background of the graphics world to a dark blue colour (which is not so different from the default black), and does nothing else.
This project lets us create a fireworks display. It offers us methods to place some firework rockets into the world, and then ignite them to set them off. At the moment, nothing much happens because the project does not place any fireworks into the world.
Let us look at the program code that is executed when we run this project. It is the code in the "My code" section of your project:
We can see two method calls and one comment. The method calls, in this order, prepare the project to be ready (including setting of the background colour) and ignite the fireworks. In the middle, we see a comment that tells us where in our code we should place our firework rockets.
A comment always starts with the symbol #, and continues with some text. The comment is ignored by the Python system; it is here only for a human reader to give us a hint. We can insert a comment into our program by adding a comment frame.
We would now like to start creating a fireworks display by placing some rockets into our world, and then igniting them.
Exercise 2.2 Delete the comment frame from your program. In its place, insert a method call frame for a method named place_rocket with a colour name as a parameter, like this:
As before, you can use colour names of all the usual web colours (a full list is in Appendix F). Run the program.
If all went well, you should now see a single fireworks rocket being fired into the night sky. The program, as it is now, prepares some internals to get the fireworks ready, places one rocket into the world, and then ignites it.
This is nice enough so far, and we could now go on to make our fireworks more interesting by adding more rockets. But we are running into a fundamental question: How do we actually know what methods are available? What are their names, what do they do, and how do we call them?
2.1.1. Reading function definitions
The three functions we are calling here, prepare(), place_rocket() and ignite(), are all defined further up in our own project. We can see the definition of these functions in the "Definitions" section:
This list shows us what functions we have available to call in our project, what their names are (in bold), and what parameters they expect (in the parentheses). They all start with the word def which is short for define, and is how Python indicates a function definition.
We can, for example, see that there is a function called ignite. The fact that it shows a pair of parentheses after the method name, with nothing inbetween, tells us that this method expects no parameters. This matches the method call in our code section, where we invoke this method without passing a parameter, like this:
If we wanted to find out more about what this method does, we can unfold its definition. This is done by clicking on the small circle outline at the far right of the function definition frame. Once we do so, the function comment is folded out, and we can see some information about this function:
Let us now look at another function: prepare(). Its definition looks like this:
Again, the "def" keyword tells us that we are looking at the definition of a function, the next word is the name of the function ("prepare"), followed by a pair of parentheses. This time, though, there is a word within the parentheses ("color"). This tells us that this function expects one parameter when it is invoked, and this parameter is called "color".
As before, we can unfold the function definition to see a function comment that gives us some more information:
The comment first tells us what this function does, and then, crucially, gives us more information about the expected parameter. Function comments are often formatted like this: They include general information about the purpose of the function, and then some information about each parameter (there may be more than one).
The parameter information starts with the line
color : str
This line tells us the type of the parameter.
The type of a parameter tells us what kind of information is expected here. Python uses several different data types to distinguish different kinds of data. These include, for example, text, whole numbers, decimal numbers or boolean (true/false) values. We will explain these types more, later in this chapter.
Internally, each type of data is handled differently, so the Python system will always keep track of what type of data it is currently working with, and often we have to be aware of this type.
In our example above, it shows the name of the parameter (color), a colon, and then the term "str". "str" is short for "string", and it means that this variable expects a segment of text (such as a word or a sentence).
The parameter information in the comment of the prepare function tells us that we should supply a parameter that is a string, and then tells us a bit more about what this string should contain (a colour name). Thus, when we call the function, we supply a value for this parameter (in our case, we used "MidnightBlue").
When we write string values in Python, we must always enclose them in quotes. Python allows us to use either double quotes or single quotes:
In this book, we will usually use double quotes for strings.
When write a function call, the call must match the function definition. If the function definition says that it expects one parameter of type string, then the function call must provide a parameter of type string. Let us look at this situation again in context. In Figure 2.1, we can see that the function definition states that the name of the function is prepare, and it expects a parameter named color. The parameter definition in the function definition is called the formal parameter – it tells us what is expected.
The function call then uses the function name to invoke the function, and it provides an actual parameter – that is, a value for the expected parameter.
Exercise 2.3 Change the actual parameter in the call to the prepare function to another colour value. Run your program to see the different background colour.
Exercise 2.4 Remove the quotes from the colour name in your function call. Run your program. What do you observe? (Afterwards, fix the problem again.)
2.1.2. Optional parameters
Let us now look back at the call to the place_rocket function which we added in an exercise above.
Exercise 2.5 Find the function definition for the place_rocket function which we used earlier. How many parameters does it have?
Exercise 2.6 What do you notice about the parameter definitions that is different to what we have seen before?
Exercise 2.7 What do you think the parameters are used for? Try to find out. (Remember that you can unfold the function definition.)
If you have completed the exercises above, you will have noticed that the number of parameters in the place_rocket function call does not match the number of formal parameters in its definition. So what is going on here?
To invoke the function, we have used the call
Looking at the definition of the function, we can see that it is
The new (and important) construct here is the =0 specification used for some of the formal parameters. This is called a default value. If a parameter has a default value, then we can leave out the actual parameter in our method call, and the default value will be used for the parameter in this case. Therefore, these two calls
achieve exactly the same thing, since the values used in the second call are exactly the same as the default values. We can, however, use values different from the defaults for the parameters. If we do, these values are used instead of the defaults.
The following calls are all valid:
Here you can see that we do not have to supply all of the values at the same time: We can override some of the defaults with different values, while leaving the later parameters to their defaults.
If we provide only some values for the parameters, but not all, the actual values are assigned to the parameters in the order of their definitions. So if we provide only one number after the colour name, it will be assigned to the target_x parameter, while the remaining two parameters use their defaults.
But what if we want to provide a value for the delay, and leave the target_x and target_y parameters to their defaults? In that case, we can specify the formal parameter name in the function call, like this:
In this case, the two middle parameters use their default values, while the color and delay parameters receive their values from the function call.
You may have worked out by now that the two middle parameters (target_x and target_y) specify the location in the world area the rocket should aim at (using the coordinate system shown in Figure 1.6), while the delay parameter specifies a delay after igniting until the rocket should fire.
Experiment with this yourself.
Exercise 2.8 Add some more rockets to your fireworks. Make them explode in different areas of the sky.
Exercise 2.9 Add some rockets that use a delay after igniting, so that not all rockets fire at the same time. (The delay value is specified in seconds.)
Exercise 2.10 Create a fireworks show that uses several rockets. It should use at least four different colours. It should also use symmetrical pairs of rockets, where two rockets of the same colour are shot to the right and left of centre, at the same angle from the vertical.
2.2. Data types: string, int and float
The first data type we have encountered above was str, which is short for "string". We have seen that the values for this type are snippets of text, written in quotes: "This is a string".
If you paid attention when you did the exercises above, you may have noticed that the comment for the place_rocket function specified that the type of the last three parameters is float. "float" is short for "floating point number", and it means that the value for this parameter should be a number that may include a decimal point. 3.14 and 0.0001 and 42.0 are all floating point numbers. It is allowed to provide numbers without a decimal point: 128, for example, will just be treated the same way as 128.0.
There is a third data type that is worth mentioning at this point, because we will encounter it very soon: int. "int" is short for "integer", which means a whole number. If a parameter type is int, then we have to supply a number, but this number cannot have a decimal point. Only whole numbers are allowed, such as 1001, -42, or 0.
| type name | full name | used for | examples |
|---|---|---|---|
str |
string |
text |
|
int |
integer |
whole numbers |
|
float |
floating point |
decimal numbers |
|
Exercise 2.11 In your fireworks display, use floating point numbers (numbers with a decimal point) for some of your delay values. For example, delay a rocket by 4.75 seconds.
After doing these exercises, you might like to compare your project to the "fireworks-finished" example from the "Chapter02" folder, which is an implementation of these exercises.
2.3. Variables and assignment
Often, when we work with bits of data, it is not enough to just pass a value to a function. We often want to store a piece of data for use later on, or for doing further computations with it. This is when we need variables.
You have seen the first variable briefly at the start of Chapter 1, when we looked at the default program in the Strype editor. Let us briefly go back to this program and look at it more closely.
Exercise 2.12 From the Strype menu (on the left hand side of the Strype window), choose the "New project" option. This will reset the editor to the default two-line program that you started with at the beginning. Run this program. What does it do?
You will see that the program consists of just two lines of code:
In this code segment, we can now recognise what the second line means: This is a function call to a function named print with one parameter. The print function is built into Python, and it prints its parameter to the Console (the text output area in the bottom right of the Strype window).
The first line is an assignment statement. We can add an assignment statement by inserting an assignment frame. A new assignment frame has two slots with an arrow symbol in the middle:
On the left side of the assignment, we can write the name of a variable. We can make up this name, and a variable with this name will be created. On the right side we write a value that we want to store in this variable. This can be any type of data that Python knows, including the three types we have seen above: strings, integers and floating point numbers.
In the example above we have stored a string into this variable ("Hello from Strype"), and we have given the variable a name that indicates that it stores a string (myString).
Exercise 2.13 Change the content of the string to a different string. Run your program.
Exercise 2.14 Write quotes around the word myString in the print method call, so that the call looks like this: print("myString"). Will this work? Run your program. What do you observe? Explain what you see. (When you are finished, remove the quotes again.)
Exercise 2.15 Change the value in the assignment (the right hand side) to a number. Run the program. Does this work?
Exercise 2.16 Once you have changed the value on the right to a number, the name of the variable is misleading: It is called "myString", but it does not hold a string. Change the name of the variable so that it accurately describes what it stores.
Exercise 2.17 Change the value on the right hand side of the assignment to 42 + 33. What do you think this will do? Try it out, and explain what happened.
Variable names must not have any spaces in them. If you need to use multiple words (for example, big fish), there are two programming conventions to do this:
-
Use underscores in place of spaces: big_fish
-
Capitalise each new word: bigFish
In this book, we generally use the first format.
2.4. Objects
In the previous section, we have seen that we can store values, such as strings or numbers, into variables. Next, let us look at a special kind of data type to store and work with: objects. To investigate this topic, we will use another project called knock-knock.
Exercise 2.18 Open the knock-knock project from the "Chapter02" folder. Run the project. Then read the code. Can you explain what the code does and how the project works?
Exercise 2.19 Change the dialog between the lobster and the crab. For example, you might find another knock-knock joke on the internet and use that one instead.
Exercise 2.20 Replace the images of the crab and lobster with different images.
This project makes use of an Actor object, which we first encountered in Chapter 1. The creation of this Actor object looks like this:
We can see that it looks very similar to a function call: It has a name, followed by a parameter list in parentheses. Because these look so similar, Python uses a convention: function names start with a lowercase character, while object types start with an uppercase character. This bit of Python code creates an object of type Actor, using the parameters provided.
In our code, we can see that we then assign this object to a variable, so that we can use it later:
This shows us that variables can also be used to store objects as values.
Before we go on and examine the rest of the program, let us ask a question: How do we know what object types and what functions exist for us to use?
Looking at our knock-knock program, we can see that it uses objects of type Actor, and functions called set_background and pause. What other objects and functions are available for us, and how do we find out?
2.5. Reading the library documentation
When working in Strype, we will often make use of objects and functions from the Strype graphics library. Over time, we will have to become familiar with most of the functions available in it. So how can we see what it offers?
The answer to this lies in the library documentation. This documentation lists all object types and functions, with all their parameters and information how to use them. In Strype, you can access this documentation by selecting "Library documentation…" from the Strype menu.
Exercise 2.21 Select the "Library documentation…" option from the Strype main menu. Examine the webpage you see. Find the documentation for the pause function. How many parameters does it have? What are the types of its parameters? What do its parameters specify?
Exercise 2.22 What are the names of the special keys that you can use with the key_pressed function?
Exercise 2.23 How many parameters does the Actor’s move method have?
Exercise 2.24 In the documentation for the Actor’s move method, what does it tell you about negative parameter values?
Learning to read this documentation will be very useful for our future programming tasks. It enables us to find out what we can do. Luckily, it is not very difficult.
The main points to understand are these:
-
The heading for this documentation is Strype API documentation. "API" is short for "Application Programming Interface", which is a technical term for the functions available in a library.
-
In the list on the left, we can see that this library contains two modules. They are called strype.graphics and strype.sound. Each module provides functions for a specific purpose, and each can be imported into our programs separately. We will investigate the strype.sound module later in this book. For now, let us concentrate on the strype.graphics module.
-
We have mentioned before that we can distinguish functions and object types by their initials: Object types start with an uppercase letter, while functions start with a lowercase letter. Knowing this, we can see that this module contains three object types (Actor, Color and Image), and a list of about a dozen functions listed below them.
-
Object types are also called classes. You can see this in the documentation when you, for example, click on
Actorin the list on the left and then look at the details of the Actor definition on the right. Its first line starts withclass Actorto tell you that this specifies a class – a type of an object. We will, from now on, also use the term "class" for types of objects. -
We can click on each of the functions in the list on the left to see a detailed description of the function, including its parameters.
-
We can also see the methods of the classes. For example, we can see the
moveandturnmethods of the Actor class, which we have used in Chapter 1.
You will quickly get used to reading this type of documentation. Having it available will help us both understand the remaining parts of the knock-knock program, as well as enable us to find out what else we could do.
Exercise 2.25 In the pace function, what is the default speed used when no actual parameter is provided?
Exercise 2.26 What does the stop function do?
Exercise 2.27 What is the difference between the say and the say_for methods of the Actor class?
We have now seen that functions and classes can be defined in two different places: They can come from a library (such as the set_background function we have used from the strype.graphics library) or they can be defined in our own project, as we have seen in the fireworks example.
2.6. Methods
In Chapter 1, we have briefly mentioned the difference between functions and methods. They are similar in that they both perform specific actions. Functions, however, perform a stand-alone action (such as set_background("red") or ignite()), while methods are actions that belong to a class and are performed by a specific object. We have seen for example, that we write
to make our fish object move. move is a method of the Actor class, as we have seen in the library documentation. There, methods are listed under the class, while functions are listed on their own at the end of the module.
Exercise 2.28 The knock-knock project contains these two lines:
Which of these lines is a function call, and which is a method call? How can you tell?
Exercise 2.29 What does the say_for method do? What is its second parameter?
Exercise 2.30 Make each of the actors (the crab and the lobster) turn a bit after every time they say something. The crab should turn left, and the lobster should turn right every time they speak.
2.6.1. The "Fat Cat" example
To continue experimenting with objects and their methods, we will use a different project: the Fat Cat project (Figure 2.2). This project defines its own class: Cat.
Exercise 2.31 Open the fatcat example from the "Chapter02" folder. Run it. What do you observe?
Exercise 2.32 How many methods does the Cat class have?
Exercise 2.33 How many parameters does the sleep method have?
Exercise 2.34 Make the cat walk a bit further than it originally did.
Exercise 2.35 Make the cat walk left instead of walking right.
Exercise 2.36 Make the cat eat.
You can see that this project defines its own class called Cat. This class is also an actor, so it is also shown in the graphics world when we create an object of this class. We can also see that the Cat class defines a number of methods which we can call on the cat.
If you have paid attention, you will have noticed one oddity: the formal parameter called self as the first parameter of all the Cat’s methods. This special parameter is needed in the method body to implement the method, but it is not used when calling the method. So the Cat method
is called using the following method call:
In other words: This parameter is used only when defining methods, but when calling methods it is ignored. Since we are – at the moment – concerned only with calling methods, we can just ignore this parameter. (In the library documentation, this parameter is not listed at all, so we are implicitly ignoring it there as well.)
Let us now experiment a little more with our cat. Instead of calling just a single method, we can also call a sequence of methods. Try this with the following exercises.
Exercise 2.37 Make the cat walk to the left, then make it eat.
Exercise 2.38 Make the cat dance, then sleep.
Exercise 2.39 Create a sequence of actions of your choice for the cat. The cat should do at least four different things.
2.7. If-statements
Looking at the Cat methods, we can see a number of methods starting with the prefix is_, for example is_hungry, is_tired, and so on. These methods return a value of either True or False, and we can use them to introduce conditional actions: make our cat do something only is a given condition is true.
In Chapter 1, we have already seen that we can use if-statements to call a method only only under certain conditions. In this case, we can, for example, make the cat eat only if it is hungry:
Try this yourself.
Exercise 2.40 Make the cat eat if it is hungry. If it is not hungry, it should do nothing.
Exercise 2.41 Change your program so that the cat dances if it is bored.
Exercise 2.42 Change your program again to do the following: If the cat is tired, it sleeps, and then it shouts hooray. If it is not tired, it just shouts hooray. (For testing, call another method first to make the cat tired. How can you make the cat tired?)
Exercise 2.43 How can you make the cat hungry? When will it be bored? Test it by writing a program that shows this.
Exercise 2.44 Change your program to do the following: If the cat is alone, let it sleep. If it is not alone, make it shout hooray. Test this by creating a second cat at the beginning of your program. The second cat should be at a different location than the first one, and its variable should be called cat2.
Exercise 2.45 Extend your program so that the second cat dances if is not alone.
If-statements can also have an else-case. An else-case is added to the if-statement by moving the frame cursor to the end of the body of the if-statement (the last line within the if-statement), and then pressing the e key. The result is an extended if-statement that looks like this:
The if-statement now has two bodies: one for the if-case, and one for the else-case. The first one is executed when the condition is true, and the second one is executed if the condition is false. Thus, one or the other of the bodies will always be executed, but never both.
Exercise 2.46 Rewrite your program to use an if-else-statement.
Exercise 2.47 Make a program with three cats. Make one cat eat, the second one sleep, and the third one dance.
Exercise 2.48 Invent your own routine for the cat (or two cats), and implement it.
You can find a version of the project that does some of these things in the book projects as fatcat-v2.
If you have done all the exercises in this chapter, you will have a good enough understanding of the Python constructs we have used thus far. We are now ready to get back to our game project and continue developing it into something more interesting.
2.8. Summary
In this chapter, we have investigated and experimented with some of the most important Python constructs. We have seen more detail about reading function definitions and calling those function. We have seen that functions can take parameters (which can include optional parameters), and that the types of the formal and actual parameters must match.
We have also discussed how to use Actor objects, and how to read the library documentation to find out more detail about what we can do with them. The documentation will be important when we work with our projects; it shows us the methods we have available.
And finally, we had a closer look at if-statements to execute specific statements only if a certain condition is true. If-statements will be useful in just about every project we write from now on.
TODO: add section about constructor/init method?




