Chapter 2. Our first Python statements

Topics:

calling functions with parameters, reading function definitions, storing values in variables, using if-statements

Constructs:

function call, function definition, parameter (formal and actual, optional), data type (str, int, float), variable, assignment, documentation, method, if-statement

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

Strype code

and the call

Strype code

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

Strype code

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.

Terminology A comment is frame that shows text for the human reader(s) of the program. It is ignored by the Python system.

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:

Strype code

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:

Strype code

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:

StrypeTip You can fold and unfold function definitions by clicking on the small circle outline in the top right corner of the function definition frame.

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.

Terminology All data in Python has a type. This distinguishes different kinds of data, such as text, numbers and boolean values.

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).

Terminology The data type string is used to store text, such as a word or a sentence. It is often abbreviated to "str". When we specify string values, we always write them in quotes, "like this".

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:

Strype code

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.

Diagram of the graphics world
Figure 2.1: A function definition and a matching function call

Concept The number and type of the actual parameters in a function call must match the number and type of the formal parameters specified in a function definition.

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.)

Note We use the terms formal parameter for the declared parameter in the function definition, and actual parameter for the value passed in with the function call. In other books you will sometimes see the terms argument and parameter instead. In this usage, the argument is the actual parameter, and the formal parameter is just called parameter.

In this book, we prefer the formal/actual parameter terms, since the stand-alone term "parameter" can be ambiguous.

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

Strype code

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

Strype code

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:

Strype code

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:

Strype code

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.

Tip Freezing functions: If you look carefully at the function definitions in the fireworks project, you see a little snowflake symbol towards the right of the function definition frame. This means that the function definition is frozen. A function is usually frozen if it should not be changed as part of the work in this project. You can freeze or unfreeze a function using the frame’s context menu (mouse right-click).

When a function is frozen, its implementation is hidden, and folding/unfolding alternates between showing the function comment, or showing only the function header. When it is unfrozen, the folding cycles through three states: header only, header with comment, full implementation.

If you provide projects for others, you can freeze a function as a signal that this function implementation should not need change, and that the user may not need to understand the implementation of this function. The function is here just to be called as it is.

If you are a learner working with a project, the frozen function tells you that you can use this function without being expected to understand how it works internally. (If you are curious, you can of course unfreeze a function and look at its implementation, but you should not need to.)

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.

Concept The three most common data types are str, int and float.

str (string) is used to store text, int (integer) is used to store whole numbers, and float (floating point number) is used to store decimal numbers. Some examples are shown in the table below.

type name full name used for examples

str

string

text

"hello"
"a"
"this is a sentence"

int

integer

whole numbers

402
0
-9

float

floating point

decimal numbers

0.001
-1.0
7654321.00002

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.

Concept We can use variables to store data for later use. Variables can be assigned a value, and later we can read that value again.

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:

Strype 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:

Strype code

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).

Concept An assignment statement stores a value into a variable. The variable name is written on the left, followed by an arrow symbol, and the value to store is written on the right.

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:

Strype code

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:

Strype code

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 Actor in the list on the left and then look at the details of the Actor definition on the right. Its first line starts with class Actor to 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 move and turn methods of the Actor class, which we have used in Chapter 1.

Terminology The type of an object is called a class. Classes define methods that can then be invoked on the objects of that class.

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

Strype code

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:

Strype code

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.

Diagram of the graphics world
Figure 2.2: The fat cat

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

Strype code

is called using the following method call:

Strype code

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.)

Tip When looking at method definitions in the Strype editor, we see the implicit "self" parameter. We can, for now, ignore this parameter.

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:

Strype code

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:

Strype code

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.

Concept An if-statement may have an else-case. The else case is optional. If it exists, it is executed when the condition is false. If the if-statement has no else case, nothing happens when the condition is false.

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.

Concept summary

  • A comment is frame that shows text for the human reader(s) of the program. It is ignored by the Python system.

  • All data in Python has a type. This distinguishes different kinds of data, such as text, numbers and boolean values.

  • The data type string is used to store text, such as a word or a sentence. It is often abbreviated to "str". When we specify string values, we always write them in quotes, "like this".

  • The number and type of the actual parameters in a function call must match the number and type of the formal parameters specified in a function definition.

  • The three most common data types are str, int and float. str (string) is used to store text, int (integer) is used to store whole numbers, and float (floating point number) is used to store decimal numbers. Some examples are shown in the table below.

  • We can use variables to store data for later use. Variables can be assigned a value, and later we can read that value again.

  • An assignment statement stores a value into a variable. The variable name is written on the left, followed by an arrow symbol, and the value to store is written on the right.

  • The type of an object is called a class. Classes define methods that can then be invoked on the objects of that class.

  • An if-statement may have an else-case. The else case is optional. If it exists, it is executed when the condition is false. If the if-statement has no else case, nothing happens when the condition is false.

TODO: add section about constructor/init method?