Thomas M. Kehrenberg

A high-level introduction to programming

Introduction

Programming is about telling a machine very very precisely what you want it to do. The program code you are writing is nothing but instructions that tell the computer what to do. The computer is in a sense very stupid because it will not do “what you meant”, but only exactly what you said. If you have a large program with millions of lines of code, one error in one line can make the whole program useless.

So, it might not surprise you that you basically cannot write a correct program on the first try – except if it’s very short. As a programmer you first write some code, test it out, discover lots of errors and then fix them. This cycle is repeated until the code is correct. Don’t be afraid to write wrong code at the beginning! Everyone does!

The other thing to know about programming is that it is basically impossible to do without re-using other people’s code. Lots of programmers publish their code in the form of so-called libraries that you can use. The typical (useful) program makes use of dozens if not hundreds of libraries that other people wrote. The idea is basically that someone solves a general problem once and then other people can use the solution.

Programming language

In general, it is not that important which programming language to learn first when learning programming: once you know one (not too weird) programming language, then learning other programming languages is relatively easy. Nevertheless, there are some languages that are generally seen as being more beginner-friendly than others.

The programming language that we will be using in this tutorial is called Python. We’re using Python because it is one of the most popular programming languages with a large community and lots of libraries. Python is also seen as beginner-friendly.

There is however one aspect of Python that I think is slightly detrimental to being used as the first language to learn: it is dynamically typed instead of statically typed. (I will explain later what types are.) I think a modern statically typed language like Swift might actually be better as a first language, but as Python is far more wide-spread than Swift, I will stick with Python.

In order to try out all the code examples, you need to use at least version 3.6 of Python which was released at the end of 2016 (any version higher than 3.6 is also fine). It’s probably easiest if you make an account at repl.it and start a new “repl” with the “Python” language. As of this writing, the default version of Python on repl.it is 3.7, so this is new enough. This tutorial will work best if you try out all the code examples yourself.

Then, let’s begin!

First steps

Consider this code:

a = 2

We stated that the variable a should have the value 2.

Let’s do something with a:

a = 2
print(a)

This puts the value of a into the output of the program. print is a function, which despite the name has little to do with printing. The function print takes the argument that you give it and evaluates it and puts it into the output of the program.

Now where does this function print come from? Well, it is part of the so-called standard library of Python. The standard library was written by the creators of the Python programming language. It contains lots of functions that are useful to all kinds of programs.

Let’s look at this code. What do you think is the output of the program?

from operator import add

a = 2
result = add(a, 4)
print(result)

Multiple things are going on here. First we have the line from operator import add. What this does is “importing” a function from the library “operator”. Importing a function means that this function is now available to be used in your code. The print function is always available in any Python program, but the add function has to be imported first. The library named “operator” is also part of the standard library of Python. Nearly all functions from the standard library have to be explicitly imported. Only very few functions are always available. print() is one of them; we will later encounter others.

So, why do we have to import most functions explicitly? There are several reasons. One is that if you were importing all functions from the standard library, then your program would be very slow to start, because all those functions have to loaded into memory. The other reason is that it could lead to namespace clashes. Which just means that there might be two functions with the same name. In this case, you can only use the function that was imported last. (There are ways to get around this issue, but we will only discuss this later.)

Okay, back to the function add. As you might be able to guess, this function takes two arguments and adds them together. This is a very nice function that someone wrote, so we don’t have to write it. Programmers use this function all the time.

Let’s write our own function using add. Don’t worry if you don’t understand what’s going on! I will explain everything.

from operator import add

def add_and_double(x: int, y: int) -> int:
single_sum = add(x, y)
double_sum = add(single_sum, single_sum)
return double_sum

a = 2
result = add_and_double(x=a, y=4)
print(result)

There are lots of things going on here. Let’s look at them one by one.

First we have the word def. Like the word import, this is a keyword. It is a word that has a special meaning in Python and you cannot use that word as the name of a variable. This:

def = 2

will give you an error and the program will not even run; let alone do what you want.

Now, while the keyword import is used to import functions, def is used to define a new function. Following def is the function name. In this case it’s “add_and_double”. In the parantheses are then the function arguments. Let’s ignore the business with the ints for now:

def add_and_double(x, y):
single_sum = add(x, y)
double_sum = add(single_sum, single_sum)
return double_sum

Our function has two arguments (or “inputs”) which we named x and y. Arguments are kind of like variables. We can give them any name we want (except names that are keywords).

After the line that starts with def, the following three lines start with 4 spaces. These spaces are very important. They tell the Python interpreter that these lines constitute the function body. This is where we define what the function is supposed to do. In this case we define a new variable called single_sum which is equal to the sum of x and y. Then we define another variable called double_sum which is equal to two times the value of single_sum. This “double sum” is supposed to be the output of the function. Thus, we use the keyword return to declare that the value of double_sum is the output of our function add_and_double(x, y). The keyword return is usually used at the end of the function body, but there are also some special cases where it’s useful to use it in other places. After the function body ends, we go back to using no spaces in front of our lines.

There is another curious thing in the code: what does the x= and y= mean in this part?

result = add_and_double(x=a, y=4)

This is called named arguments. In Python, when you call a function, you have the option to explicitly name the arguments that you are passing to the function. We could also have done this:

result = add_and_double(a, 4)

It would have had the same effect. When using named arguments, it is important to use the exact right names. We can not do this:

result = add_and_double(h=a, u=4)

This will give an error because in the definition of the function add_and_double we used the names x and y for the arguments; and not h and u.

Named arguments have several advantages. They can make the function call easier to understand (more on that later), they can prevent you from making mistakes (more on that later as well) and you are able to change the order of the arguments:

result = add_and_double(y=4, x=a)

This is valid. You should use named arguments whenever it’s not too cumbersome.

Now let’s add back the ints. What are they about?

def add_and_double(x: int, y: int) -> int:
single_sum = add(x, y)
double_sum = add(single_sum, single_sum)
return double_sum

int specifies a type. What is a type?

Types

The type tells you what type of data a variable holds. In our case, the variables hold numbers. More specifically, whole numbers, which are integers. And that’s what the type int refers to: integers. x: int simply means that x is supposed to be an integer. And the -> int means that the output of the function is also an integer.

Now, in Python, specifying types is actually not very meaningful. This is to me a negative property of Python. In other languages, the type is much more meaningful and useful. In Python, you can write

a: int = 0.34

and the program will still work completely fine, even though the variable a does not hold an integer (0.34 is not a whole number). But you still need to know about types when using Python: (basically) all functions in Python expect certain types as inputs and if you supply a variable with the wrong type, then you will get an error.

For example, our functions takes two inputs and adds them together. And you can only do that with numbers! So, in order for our function to work, x and y have to be numbers. Another function might take other types as inputs.

What other types of data are there? The most basic ones are: int, float, str and bool. All the other data types are basically combinations of these. Let’s go through them.

float

This type is for floating point numbers which refers to numbers like 3.2 or 0.003. So, not whole numbers. Our add_and_double(x, y) function could actually also have accepted floats as arguments. We can define a variable with a float value like so:

pi: float = 3.14

As you would expect, you can use the add function with variables of this type:

pi: float = 3.14
double_pi = add(pi, pi)

Now, you might wonder: if we have float, why do we even need int? After all, int is a subset of float: for every integer like 4, there is a floating point number 4.0. The answer is that it is often useful to restrict an argument to int. But there are in fact programming languages that don’t have ints; only floats (e.g. JavaScript).

str

This is the type for text. Why is this type called str and not, for example, text or letters? It comes from “string of characters” and was defined in the 1960s. It’s not the greatest name, but basically all programming languages use it.

When we define a string variable, we use quotation marks:

greeting: str = "Hello, world!"

Of course, a string can also contain a random mix of letters and numbers:

nonsense: str = "2d;l8dfh;348fhea"

It’s important to note that, for example, 9 and "9" mean two very different things. These two variables do not contain the same value:

a: int = 9
b: str = "9"

The first one contains a number that can be used to do math. The second one is a string that happens to have a number in it. The computer stores these very differently. This can be a bit confusing at the beginning.

A string is something that our function add_and_double(x, y) probably should not accept as an argument. And indeed if you try to do

f = addAndDouble(x="Hello", y=2)

you will get an error. Which is good, because it doesn’t make any sense.

bool

This type might be a bit weird at first, but it is very useful. Variables that have type bool can only have 1 of 2 values: True or False. The names True and False are keywords that cannot be used for variable names. So, we might write:

nice_weather: bool = True

The name of the type, bool, comes from the mathematician George Boole. The usefulness of this type will become clear when we have introduced if-statements.

Type conversion

Sometimes you want to turn a float to an int or an int to a string. You can do this by using the type name like a function:

a: float = 1.7
b: int = int(a)

b now has the value 1. When apply the function int() to a float then everything after the point is simply cut off. If you want to round correctly, use the function round(). Just like print(), round() is always available.

c: int = round(1.7)

Here c will have the value 2.

What if you want a float variable with the value 2? You can either write 2.0, which is always a float or you can write float(2). Usually, the first variant is preferred.

Integers and floats can also easily be converted to strings:

d: str = str(6.78)

d will have the value "6.78".

Recap

Let’s recap what we have learned. This:

def add_and_double(x: int, y: int) -> int:
single_sum = add(x, y)
double_sum = add(single_sum, single_sum)
return double_sum

defines a function which takes two integers and gives one integer back, which is two times the sum of the two inputs.

This code gives an error:

greeting = "Hello"
result = add_and_double(x=greeting, y=2)

because the variable greeting contains a string (i.e. text) which cannot be added to an int.

In our examples, we have made use of two functions from the standard library: print and add. There are of course many more. Amongst them for example sub for subtracting, mul for multiplying and truediv for dividing numbers. They are all in operator:

from operator import sub, mul, truediv

(The name truediv is meant to distinguish it from floordiv, but we’re not getting into why there are two functions for division now.)

We have also already encountered the following keywords: import, from, def, return, True, False. But there are a few more keywords to discover.