8. Funktionen erstellen

Video link ../../_images/teacher.svg

In the last chapter we learned how to create variables and use them in expressions. In this chapter we are going to build on that knowledge to create functions. Functions are groups of commands we give to the computer. We’ve already used functions, for example the print function and the draw_line function. Now we are going to learn to make our own functions.

Functions help us by:

  • Making our code easier to read. By writing our own functions we can have functions to draw_tree and draw_horse which is a lot easier to read than long blocks of code that just draw lines and rectangles.

  • Abstracting our code. By using variables, we can abstract our code and tell a function where to draw a tree, how big to draw it, and what color to draw it. This is a lot more flexible than one set of code that can only draw a tree in one exact place and one exact size.

  • Re-using our code. By calling a function, I can re-use code over and over. If it takes ten lines of code to draw a horse, I can put that in a function. Then if I want to draw three horses, I don’t need thirty lines of code to do it.

  • Dividing a complex problem into simpler ones. The key to programming, and a lot of things in life, is to learn how to take a large, overwhelmingly complex problem, and divide it into small problems. For example, we have functions that can display dots on the screen. Then there functions that can draw a line using those dots. Then functions that can draw triangles using those lines. Then functions that can draw trees using those triangles. Then finally a forest function that uses the trees function. Drawing a complex forest is broken down into simple functions that build off each other.

  • Making code easier to maintain. If there is a problem in your program, it is easier to find when your program is divided into parts. If your car isn’t moving correctly, and there is a move_car function, that’s easy to find. Plus, if all cars move using that function, I can fix a problem for every car in my game in one spot.

8.1. Einfache Funktionen erstellen

Defining a function in Python is easy. Here’s an example:

Defining a function.
1
2
3
def print_hello():
    """ This is a comment that describes the function. """
    print("Hello!")

To write a function:

  • Fange mit dem Schlüsselwort def, kurz für define, an.

  • Next, give the function a name. Function names follow the same rules that variable names follow. They must:

    • Start with a lower case letter. (Or in special cases, an underscore.)

    • Nach dem ersten Buchstaben dürfen nur weitere Buchstaben, Ziffern und der Unterstrich folgen.

    • Leerzeichen sind nicht erlaubt. Verwende stattdessen Unterstriche.

    • Obwohl Großbuchstaben erlaubt sind, bestehen Funktionsnamen normalerweise nur aus Kleinbuchstaben.

  • Danach folgt ein Klammernpaar. In das Klammernpaar kommen die Parameter. Wir erklären das in Kürze.

  • Danach ein Doppelpunkt.

  • All the code that goes in the function will be on the following lines. That code must be indented four spaces. The first line that is not indented, signifies the function is done.

  • Üblicherweise starten wir eine Funktion mit einem mehrzeiligen Kommentar, der erklärt, was die Funktion tut.

Bemerkung

Funktionsdefinition gehören hinter die import-Anweisungen und vor den Rest des Programms. Du könntest sie auch woanders hinschreiben, aber das solltest du nicht tun.

Defining a function doesn’t cause the computer to do anything. It is like giving a recipe to the computer. Give someone a recipe for banana bread and they know how to make it. They haven’t actually made it yet, they just know how. You have to tell them to make banana bread. That is, after we define the function we must call the function before the code in it runs.

To call a function, type the function name and follow it by parenthesis. Do not use def, that is only used when we define what the function does, not when we tell the computer to run it.

Below is a program that defines print_hello, then calls it twice.

Defining and calling a function.
1
2
3
4
5
6
7
def print_hello():
    """ This is a comment that describes the function. """
    print("Hello!")

# This calls our function twice.
print_hello()
print_hello()

You can define and use multiple functions. But all function definitions should go before the main code. In this example, see how we’ve defined two functions and then we call them in our main code.

Defining and calling multiple functions.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def print_hello():
    print("Hello!")


def print_goodbye():
    print("Bye!")

# Here is the main code, after all the function
# definitions.
print_hello()
print_goodbye()

8.2. Creating a Main Function

Es sollte sogar fast der gesamte Programmcode in Funktionen stehen. Es gehört zu einer vorbildlichen Vorgehensweise, den Startpunkt deines Programms in eine Funktion namens main zu packen und aufzurufen,

In this next example, we do just that. See how we took the two function calls and put them in a main function. Also, note that we call main at the end. Without that, our program won’t do anything at all.

Using a main function.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
def print_hello():
    print("Hello!")


def print_goodbye():
    print("Bye!")


def main():
    """ This is my main program function """
    print_hello()
    print_goodbye()


# Call (run) the main function
main()

Remember how our drawing code always starts with import arcade? That just imports a lot of functions that are defined in the Arcade library so we can use those functions ourselves. It doesn’t run anything, just imports functions.

Eventually we’ll learn to write our own modules we import. Right now, we couldn’t do that with our code because attempting to import the code would actually run it. What we want is simply to make the functions available for us to use.

With that in mind, a better habit to get into is to check if we are trying to import the file before calling the main function. The statement, in this next example, looks a little weird. In fact, it is weird enough I just look it up and copy/paste it any time I want to use it. Don’t worry about understanding how it works yet, just realize it is a good practice and why.

Check to make sure we aren’t importing the file before calling main.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
def print_hello():
    print("Hello!")


def print_goodbye():
    print("Bye!")


def main():
    print_hello()
    print_goodbye()


# Only run the main function if we are running this file. Don't run it
# if we are importing this file.
if __name__ == "__main__":
    main()

If this is too confusing, just call the main() method instead. Eventually we’ll learn about imports and if statements. Then it will make more sense.

8.3. Take in Data with Parameters

../../_images/data.svg

Functions are even more powerful if we can feed data into them to process.

Here is a simple example that will take in a number and print it. Notice how I’ve created a new variable my_number in between the parenthesis. This is called a function parameter. It is just a variable that is given a value equal to what is passed in when called. In the example below, it is given first a 55, then 25, and finally an 8.

1
2
3
4
5
6
7
def print_number(my_number):
    print(my_number)


print_number(55)
print_number(25)
print_number(8)

You can pass in multiple numbers, just separate them with a comma. In this case a will be 11 and b will be 7.

1
2
3
4
5
def add_numbers(a, b):
    print(a + b)


add_numbers(11, 7)

Occasionally, new programmers want to set the parameter values inside the function. This is wrong. If you do this, the function would only work for those values. The power is in specifying the numbers outside the function. We don’t want the function to be limited to only certain data values.

This example works, but it is wrong. Because if we ever changed line 8 to pass in different values, the program would ignore those values because on lines 3 and 4 they are always over written with 11 and 7.

1
2
3
4
5
6
7
8
# This is wrong
def add_numbers(a, b):
    a = 11
    b = 7
    print(a + b)


add_numbers(11, 7)

8.4. Werte zurückgeben und weiterverarbeiten

Functions can not only take in values, functions can return values.

8.4.1. Werte zurückgeben

For example, here is a function that returns two numbers added together. See how it uses a return statement on line four to return the result out of the function.

1
2
3
4
# Add two numbers and return the results
def sum_two_numbers(a, b):
    result = a + b
    return result

Bemerkung

Return is not a function, and does not use parentheses. Don’t do return(result).

This only gets us half-way there. Because if we call the function now, not much happens. Take a look at this example:

# This doesn't do much, because we don't capture the result
sum_two_numbers(22, 15)

The numbers get added. They get returned to us. But we do nothing with the result. So if you run this program, nothing prints to the screen and we can’t tell that anything happened.

8.4.2. Zurückgegeben Wert weiterverarbeiten

../../_images/catch.svg

We need to capture the result. We do that by setting a variable equal to the value the function returned. In this next code example we capture the result by putting a variable to the left of the function call and using the = (assignment) operator. Later the code prints the value, but that’s not capturing! That is just using the result we captured and printing it.

# Capture the function's result into a variable
# by putting "my_result =" in front of it.
# (Use whatever variable name best describes the data,
# don't blindly use 'my_result' for everything.)
my_result = sum_two_numbers(22, 15) # <--- This line CAPTURES the return value

# Now that I captured the result, print it.
print(my_result) # <--- This is printing, NOT capturing.

Now the result isn’t lost. It is stored in the my_result variable which we can print or use some other way.

We will do this a lot, so pause for a second and set it sit in your mind. I’ll wait.

Great, now imagine you have an instructor or co-worker watching over your shoulder. You have a function. It returns a value. The person over your shoulder says, „Ok, now you just have to capture the value.“ The pressure is on.

Don’t panic! Remember to capture the value returned from a function, put a variable to the left of it and use an = operator.

8.4.3. Beispiel Zylindervolumen

../../_images/cans.svg

Let’s use what we learned for something more practical. Here is a function that returns the volume of a cylinder. Notice how we take in two parameters and return the result of the calculation.

1
2
3
4
def volume_cylinder(radius, height):
    pi = 3.141592653589
    volume = pi * radius ** 2 * height
    return volume

Because of the return, this function could be used later on as part of an equation to calculate the volume of a six-pack like this:

six_pack_volume = volume_cylinder(2.5, 5) * 6

See how the value returned from volume_cylinder goes into the equation and is multiplied by six. We would not be able to chain together calculations like that if all we could do was print, instead of return.

There is a big difference between a function that prints a value and a function that returns a value. Look at the code below. Pause for a bit and make sure you can follow how it works. Read the comments. This is a common source of confusion for new programmers, so spend a bit of time studying it.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# This function will print the result
def sum_print(a, b):
    result = a + b
    print(result)


# This function will return the result
def sum_return(a, b):
    result = a + b
    return result


# This code prints the sum of 4+4, because the function has a print
sum_print(4, 4)

# This code prints nothing, because the function returns, and doesn't print
sum_return(4, 4)

# This code will not set x1 to the sum.
# The sum_print function does not have a return statement, so it returns
# nothing!
# x1 actually gets a value of 'None' because nothing was returned
x1 = sum_print(4, 4)
print("x1 =", x1)

# This will set x2 to the sum and print it properly.
x2 = sum_return(4, 4)
print("x2 =", x2)

This next code example has a very common issue new programmers face. It is not unusual to get stuck looking at code like this example below. Your task: how would you print the result of the function? See if you can figure it out without looking ahead.

def calculate_average(a, b):
    """ Calculate an average of two numbers """
    result = (a + b) / 2
    return result


# Pretend you have some code here
x = 45
y = 56

# Wait, how do I print the result of this?
calculate_average(x, y)

What’s the answer? How do we print the result of calculate_average? In the code above, the program can’t print the result because the result variable only exists inside the function. Instead, use a new variable outside the function, and the = operator to capture the result:

def calculate_average(a, b):
    """ Calculate an average of two numbers """
    result = (a + b) / 2
    return result


# Pretend you have some code here
x = 45
y = 56

average = calculate_average(x, y)
print(average)

8.5. Funktionen dokumentieren

../../_images/document.svg

Functions in Python typically have a comment as the first statement of the function. This comment is delimited using three double quotes, and is called a docstring. In this case, the docstring is on line 2:

1
2
3
4
5
def volume_cylinder(radius, height):
    """Returns volume of a cylinder given radius, height."""
    pi = 3.141592653589
    volume = pi * radius ** 2 * height
    return volume

The great thing about using docstrings in functions is that the comment can be pulled out and put into a website. That can be part of a larger website that documents your code. For example, here is the documentation for drawing a circle, generated automatically from the function comment. In fact, everything on that page is automatically generated. Most languages have similar tools that can help make documenting a breeze. This can save a lot of time as you start working on larger programs.

8.6. Gültigkeitsbereich von Variablen

../../_images/telescope.svg

The use of functions introduces the concept of scope. Scope is where in the code a variable is „alive“ and can be accessed. For example, look at the code below:

# Define a simple function that sets
# x equal to 22
def f():
    x = 22


# Call the function
f()
# This fails, x only exists in f()
print(x)

The last line will generate an error because x only exists inside of the f() function. Every heard the phrase „What happens in Vegas, stays in Vegas?“ Well, variables created in a function stay in the function. The variable is created when f() is called and the memory it uses is freed as soon as f() finishes.

Here’s where it gets complicated. A more confusing rule is how to access variables created outside of the f() function. In the following code, x is created before the f() function, and thus can be read from inside the f() function.

# Create the x variable and set to 44
x = 44


# Define a simple function that prints x
def f():
    print(x)


# Call the function
f()

Variables created ahead of a function may be read inside of the function only if the function does not change the value. This code, very similar to the code above, will fail. The computer will claim it doesn’t know what x is.

# Create the x variable and set to 44
x = 44


# Define a simple function that prints x
def f():
    x += 1
    print(x)


# Call the function
f()

8.7. Als Kopie übergeben

../../_images/copy.svg

When you call a function and set a value to a function parameter, that value is a copy of the original. For example take a look at this code:

# Define a simple function that prints x
def f(x):
    x += 1
    print(x)


# Set y
y = 10
# Call the function
f(y)
# Print y to see if it changed
print(y)

The value of y does not change, even though the f() function increases the value passed to it. Each of the variables listed as a parameter in a function is a brand new variable. The value of that variable is copied from where it is called.

This is reasonably straight forward in the prior example. Where it gets confusing is if both the code that calls the function and the function itself have variables named the same. The code below is identical to the prior listing, but rather than use y it uses x.

# Define a simple function that prints x
def f(x):
    x += 1
    print(x)


# Set x
x = 10
# Call the function
f(x)
# Print x to see if it changed
print(x)

Die Ausgabe ist die gleiche wie vorher. Obwohl die Funktion und der umgebende Code x als Variablennamen verwenden, sind es doch tatsächlich zwei verschiedene Variablen. Die eine Variable x existiert innerhalb der Funktion. Die andere Variable x existiert außerhalb der Funktion.

8.8. Funktionen rufen Funktionen auf

Überlege dir bei jedem der Beispiele unten, was es ausgeben wird. Überprüfe, ob du recht hattest. Wenn du falsch lagst, verwende Zeit darauf zu verstehen warum.

8.8.1. Beispiel 1

Beachte in diesem Beispiel, dass eine Funktion nur ausgeführt wird, wenn sie auch aufgerufen wird.

# Example 1
def a():
    print("A")


def b():
    print("B")


def c():
    print("C")


a()

8.8.2. Beispiel 2

# Example 2
def a():
    b()
    print("A")


def b():
    c()
    print("B")


def c():
    print("C")


a()

8.8.3. Beispiel 3

# Example 3
def a():
    print("A")
    b()


def b():
    print("B")
    c()


def c():
    print("C")


a()

8.8.4. Beispiel 4

# Example 4
def a():
    print("A start")
    b()
    print("A end")


def b():
    print("B start")
    c()
    print("B end")


def c():
    print("C start and end")


a()

8.8.5. Beispiel 5

# Example 5
def a(x):
    print("A start, x =", x)
    b(x + 1)
    print("A end, x =", x)


def b(x):
    print("B start, x =", x)
    c(x + 1)
    print("B end, x =", x)


def c(x):
    print("C start and end, x =", x)


a(5)

8.8.6. Beispiel 6

In Zeile 3 dieses Beispiel wird der Wert von x inkrementiert. Da aber die Variable x in der Funktion eine andere Variable ist, als x im Rest des Programms, ändert sich der angezeigte Wert nicht.

# Example 6
def a(x):
    x = x + 1


x = 3
a(x)

print(x)

8.8.7. Beispiel 7

In diesem Beispiel, das dem vorherigen ähnelt, geben wir x zurück. Es zeigt sich, dass das keinen Unterschied macht, da wir mit dem Rückgabewert nichts machen. Die globale Variable x erhöht sich immer noch nicht. Sieh dir das nächste Beispiel an.

# Example 7
def a(x):
    x = x + 1
    return x


x = 3
a(x)

print(x)

8.8.8. Beispiel 8

In diesem Beispiel nehmen wir den von a() zurückgegebenen Wert und speichern ihn in der Variablen x. Wie? Durch Schreiben von x = a(x) statt nur a(x).

# Example 8
def a(x):
    x = x + 1
    return x


x = 3
x = a(x)

print(x)

8.8.9. Beispiel 9

# Example 9
def a(x, y):
    x = x + 1
    y = y + 1
    print(x, y)


x = 10
y = 20
a(y, x)

8.8.10. Beispiel 10

Obwohl man mehrere return-Anweisungen in einer Funktion haben kann, endet die Funktion mit dem ersten return. In diesem Beispiel wird return y niemals ausgeführt, wir von der Funktion schon in der Zeile davor zurückgekehrt sind.

# Example 10
def a(x, y):
    x = x + 1
    y = y + 1
    return x
    return y


x = 10
y = 20
z = a(x, y)

print(z)

8.8.11. Beispiel 11

Dies ist etwas, das man nicht in jeder Programmiersprache machen kann. Du kannst zwei Werte auf einmal zurückgeben, indem du sie mit einem Komma getrennt angibst.

# Example 11
def a(x, y):
    x = x + 1
    y = y + 1
    return x, y


x = 10
y = 20
z = a(x, y)

print(z)

8.8.12. Beispiel 12

Wenn du zwei Werte aus einer Funktion zurück gibst, kannst du sie in dieser vor weiterverarbeiten.

# Example 12
def a(x, y):
    x = x + 1
    y = y + 1
    return x, y


x = 10
y = 20
x2, y2 = a(x, y) # Most computer languages don't support this

print(x2)
print(y2)

8.8.13. Beispiel 13

# Example 13
def a(my_data):
    print("function a, my_data =  ", my_data)
    my_data = 20
    print("function a, my_data =  ", my_data)


my_data = 10

print("global scope, my_data =", my_data)
a(my_data)
print("global scope, my_data =", my_data)

8.8.14. Beispiel 14

Wir werden mehr über die nächsten beiden Beispiele reden, wenn wir „Listen“ und „Klassen“ behandeln. Diese Beispiele funktionieren nicht so, wie du das vielleicht zuerst erwartest. Sieh dir an, was unterschiedlich ist. Wir werden später erklären, warum dies anders funktioniert.

# Example 14
def a(my_list):
    print("function a, list =  ", my_list)
    my_list = [10, 20, 30]
    print("function a, list =  ", my_list)


my_list = [5, 2, 4]

print("global scope, list =", my_list)
a(my_list)
print("global scope, list =", my_list)

8.8.15. Beispiel 15

# Example 15
# New concept!
# Covered in more detail in a later chapter
def a(my_list):
    print("function a, list =  ", my_list)
    my_list[0] = 1000
    print("function a, list =  ", my_list)


my_list = [5, 2, 4]

print("global scope, list =", my_list)
a(my_list)
print("global scope, list =", my_list)

8.9. Review

This chapter was all about functions. We learned how to define functions using the def keyword. We can call functions just by using the function name followed by parenthesis. Functions can take in data by using parameters. Functions return data using the return statement. We can capture that data by setting a variable equal to the function call. Functions can be documented with comments. Variables created inside a function cannot be accessed outside the function. Parameter variables contain copies of the original data and can be modified without changing the original. Functions can call other functions, which can call yet more functions.