Skip to main content
`Ctrl`+`K`

# Building Blocks

We start our quick run through Python with essential features which can be found in almost every high-level programming language. What we will meet here is known as structured programming. Later on we will move on to object oriented programming.

## Comments

A Python source code file may contain text ignored by the Python interpreter. Such comments help to understand and document the source code. Everything following a `#` symbol is ignored by the interpreter.

    a = 1    # here we could place some explanation

    # this whole line is a comment and completely ignored by the interpreter
    b = 2

For the Python interpreter the above code is equivalent to

    a = 1
    b = 2

Note that empty lines do not matter. We may place empty lines everywhere like comments to make the code more readable.

## Assignments

Data (numbers, strings and other) in memory can be associated to a human readable string. Such a combination of a piece of data and a name for it is known as variable. To assign a name to a piece of data Python uses the `=` sign.

    a = 1

The above code writes the number 1 to some location in memory and assigns the name `a` to it. Whenever we want to use or modify this value we simply have to provide its name `a`. The Python interpreter translates the name into a memory address.

    print(a)

    1

This prints the value of the variable `a` to screen.

## Simple Data Types

We have to distiguish different types of data because each type comes with its own set of operations. Numbers can be added and multiplied, for example, whereas strings can be concatenated but not multiplied. In Python we do not have to care too much about choosing the correct data type, because the interpreter does much of the technical stuff (e.g., how much memory is required?) for us.

    a = 2           # an integer
    b = 2.1         # a floating point number
    c = "Hello!"    # a string
    d = True        # a boolean value

    print(a)
    print(b)
    print(c)
    print(d)

    2
    2.1
    Hello!
    True

### Integers

Integers are the numbers …, -2, -1, 0, 1, 2,….

Note

In most programming languages there is a maxmimum value an integer can attain, like \(-2^{31},...,2^{31}+1\). In Python there is no limit on the size of an integer.

    a = 5 + 2     # addition
    b = 5 - 2     # substraction
    c = 5 * 2     # multiplication
    d = 5 // 2    # floor division
    e = 5 % 2     # remainder of devision
    f = 5 / 2     # division (yields a floating point number)
    g = 2 ** 5    # power

    print(a)
    print(b)
    print(c)
    print(d)
    print(e)
    print(f)
    print(g)

    7
    3
    10
    2
    1
    2.5
    32

Undefined operations will be identified by the interpreter.

    a = 1 // 0

    ---------------------------------------------------------------------------
    ZeroDivisionError                         Traceback (most recent call last)
    Input In [7], in <cell line: 1>()
    ----> 1 a = 1 // 0

    ZeroDivisionError: integer division or modulo by zero

If we want the user to input an integer, we may use the following code

    a = int(input("Give me an integer: "))
    print(a)

Like `print` and `input` also `int` is a function. It takes a string and converts it to an integer. If this is not possible, an error message appears and program execution is stopped.

### Floating Point Numbers

Python supports floating point numbers (also known as floats) in the approximate range 1e-308…1e+308 with 15 significant decimal places (double precision in IEEE 754 standard). Floating point numbers are stored as a pair of coefficient and exponent of 2, where both coefficient and exponent are integers.

Example: \(0.1875=3\cdot 2^{-4}\) with coefficient 3 and exponent -4.

Important

Most decimal fractions cannot be represented exactly as float, which may cause tiny errors in computations.

Example:

\[\begin{align*} 0.1&\approx 3602879701896397\cdot 2^{-55}\\ &=0.1000000000000000055511151231257827021181583404541015625 \end{align*}\]

See Python documentation for more detailed explanation and additional examples.

    a = 5        # integer (stored as is)
    b = 5.0      # float (stored as coefficient and exponent)
    c = 5.123    # float
    d = c + 2    # float plus integer yields float

    print(a)
    print(b)
    print(c)
    print(d)

    5
    5.0
    5.123
    7.123

Note that Python converts data types automatically as needed. Destination type is chosen to prevent loss of data as far as possible (cf. line 4 in the code example above). If conversion is not possible, the interpreter will complain about.

### Strings

In Python strings are as simple as numbers. Just enclose some characters in single or double quotation marks and they will become a Python string.

    a = 'Hello'      # single quotation marks
    b = 'my'
    c = "friend!"    # double quotation marks

    # strings may be concatenated using +
    d = a + ' ' + b + ' ' + c

    print(d)

    Hello my friend!

Behavior of operators like `+` depends on the data type of the operands. Adding two integers `123 + 456` yields the integer `579`. Adding two strings `'123' + '456'` yields the string `'123456'`.

If a string contains single quotation marks, then use double quotation marks and vice versa. Alternatively, you may escape quotation marks in a string with a backslash.

    a = "He isn't cool."
    b = 'He isn\'t cool.'
    c = 'He said: "Your are crazy"'
    d = "He said: \"Your are crazy\""

    print(a)
    print(b)
    print(c)
    print(d)

    He isn't cool.
    He isn't cool.
    He said: "Your are crazy"
    He said: "Your are crazy"

### Boolean Values

Boolean values or truth values can hold either `True` or `False`. Typically, they are the result of comparisons. Boolean values support logical operations like `and`, `or`, and `not` (see Logic).

    a = True
    b = a and False
    c = not a
    d = a or b

    print(a)
    print(b)
    print(c)
    print(d)

    True
    False
    False
    True

## Functions

A function is a piece of Python code with a name. To execute the code we have to write its name, optionally followed by parameters (sometimes denoted as arguments) influencing the function’s code execution. After executing the function some value can be returned to the caller.

This concept is required in two circumstances:

- a piece of code is needed several times,

- readability shall be increased by hiding some code.

### Built-in Functions

Python has several built-in functions, like `print` and `input`. The `print` function takes one or more variables and prints them on screen. In case of multiple arguments outputs are separated by spaces. The `input` function may be called without arguments. It waits for user input and returns the input to the calling code.

    a = input()
    print('You typed:', a)

Above we also met the `int` function, which converts a string to an integer if possible. The `int` function behaves exactly in the same way as all other functions, but it is not a built-in function in the stricter sense. Instead, it’s the constructor of a class, a concept we’ll discuss later on.

### Keyword Arguments

Functions accept different kinds of arguments. Some are passed as they are (like for `print`). Those are called positional arguments and we meet them in almost all programming languages.

In Python often we’ll see function calls of the form `some_function(argument_name=passed_value)`. Such arguments are called keyword arguments and help to increase code readability. If a function accepts multiple keyword arguments, we do not have to care about which one to pass first, second and so on. Details will be discussed in a separate chapter on functions later on.

### Function Definitions

We can define new functions with the `def` keyword.

    def say_hello(name):
        ''' Print a hello message. '''

        message = 'Hello ' + name + '!'
        print(message)

    say_hello('John')
    say_hello('Anna')

    Hello John!
    Hello Anna!

Note the indentation of the function’s code and the docstring `'''...'''`. The indentation tells the Python interpreter which lines of code belong to the function. The docstring is ignored by the interpreter like a comment. But tools for automatic generation of software documentation extract the docstring and process it.

To return a value (like `input` does) we would have to add a line containing `return my_value`. The `return` keyword stops execution of the function and returns control to the calling code. We place `return` wherever appropriate for our purposes. Often, but not always, it’s in the last line of the function’s code.

Important

Variables introduced inside a function, like `message` above, are only accessible inside that function. But variables defined outside a function are accessible inside functions, too. It’s considered good practice to keep inside and outside variables separated. That is, don’t use outside variables inside a function. Instead pass all values required by the function as arguments and return results required outside a function with `return`. Exceptions prove the rule.

### Errors in Functions

If there is an error in a function’s code, the Python interpreter will show an error message together with a traceback. That’s a list of code lines leading to the erroneous line. If a program calls a function which again calls a function which contains an error, the traceback will have three entries.

In the following example the variable name is incorrect in the `print` line.

    def say_hello(name):
        ''' Print a hello message. '''

        message = 'Hello ' + name + '!'
        print(mesage)

    say_hello('John')
    say_hello('Anna')

    ---------------------------------------------------------------------------
    NameError                                 Traceback (most recent call last)
    Input In [15], in <cell line: 8>()
          4     message = 'Hello ' + name + '!'
          5     print(mesage)
    ----> 8 say_hello('John')
          9 say_hello('Anna')

    Input In [15], in say_hello(name)
          2 ''' Print a hello message. '''
          4 message = 'Hello ' + name + '!'
    ----> 5 print(mesage)

    NameError: name 'mesage' is not defined

If there would be an error in `print` (because you passed an unexpected argument, for instance), then the traceback would have an additional entry showing the erroneous line in the definition of `print`.

Hint

Tracebacks may become very long if your code implies a problem in some built-in or library function. Check the traceback carefully to find the last entry referring to your code. That’s the most likely location of the problem’s cause.

## Conditional Execution

Up to now program flow is linear. There is one path and the interpreter will follow this path. Here comes the first element of flow control: conditional execution.

    a = int(input('Give me a number: '))
    b = int(input('Give me another number: '))

    if a > b:
        print('First number is greater.')
    else:
        print('First number is not greater.')

If the condition is satisfied, then the first code block is executed. If it is not satisfied, the `else` block is executed. For equality use `==`, for inequality use `!=`. Other comparison operators are `<`, `>`, `<=`, `>=`.

A comparison evaluates to a boolean value. Thus, more complex conditions can be constructed with the help of boolean operators.

    a = int(input('Choose a number from 1 to 10: '))

    if (a >= 1) and (a <= 10):
        print('Well done!')
    else:
        print('You still have to learn a lot...')

The `else` part can be omitted, if nothing is to be done.

If more than two cases (`True` and `False`) have to be distinguished, use `elif`, which stands for ‘else if’:

    a = int(input('Give me an integer: '))

    if a < 0:
        print('It\'s a negative number.')
    elif a == 0:
        print('It\'s zero.')
    elif a < 10:
        print('It\'s a small positive number.')
    else:
        print('It\'s a large positive number.')

## Repeated Execution

The second element of flow control, next to conditional execution, is repeated execution. Python provides two techniques: while loops and for loops.

### For Loops

A for loop repeats a code block a pre-specified number of times.

    for k in range(1, 10):
        print(k * k)

    1
    4
    9
    16
    25
    36
    49
    64
    81

Note that 100 is not printed. The loop always stops before the final number is reached.

Note

Whenever you have to define a range of integers in Python the upper bound has to be the last value you need plus 1. If you already tried some other programming language, this peculiarity of Python needs getting used to.

### While Loops

A while loop repeats a code block as long as a condition is met.

    my_number = 10

    users_number = int(input('Guess my number: '))

    while users_number != my_number:
        if users_number < my_number:
            print('Too small!')
        else:
            print('Too large!')
        users_number = int(input('One more chance: '))

    print('Correct!')

### No Do-While Loops

Many programming languages have a so called do-while loop. That’s like a while loop, but the condition is checked at the loop’s end. Thus, the loop’s code block is executed at least once. Python does not have a while loop.

Guido van Rossum, Python’s BDFL, rejected a Python enhancement proposal (PEP) which suggested to introduce a do-while loop with the following words:

> Please reject the PEP. More variations along these lines won’t make the language more elegant or easier to learn. They’d just save a few hasty folks some typing while making others who have to read/maintain their code wonder what it means.

### Controlling Loop Execution

For and while loops provide the keywords `break` and `continue`. With `break` we can abort execution of the loop. With `continue` we can stop execution of the loop’s code block and immediately begin the next iteration.

Loops may have an `else` code block. The `else` block is executed if iteration terminates regularly. It is skipped, if iteration is stopped by `break`.

    for k in range(1, 10):
        print(k)
        a = input('Do you want to see the next number (y/n)?')
        if a == 'n':
            break
    else:
        print('Now you\'ve seen all my numbers.')
    print('Good bye!')

Note

Whereas for and while loops are available in almost all programming languages, the `else` block is a special feature of Python.

## Lists

Next to the simple data types above there are more complex ones. Here we restrict our attention to lists. A list can hold a number of values. The length of a list is returned by the built-in function `len`. Square brackets `[` and `]` are used for defining a list and for accessing single elements of a list.

    a = [2, -5, 4, 3, 2, -10, 3, 4]

    print('List:', a)

    print('Length of list:', len(a))

    print('First element:', a[0])

    print('Second element:', a[1])

    print('Fifth element:', a[4])

    print('Last element:', a[len(a) - 1])

    List: [2, -5, 4, 3, 2, -10, 3, 4]
    Length of list: 8
    First element: 2
    Second element: -5
    Fifth element: 2
    Last element: 4

List indices start with 0 in Python. Consequently, the last element of an n-element list has index n-1. The above code to access the last element is considered non-pythonic. Why this is the case and how to make it better will be discussed later on.

Lists may contain arbitrary types of data. Even lists of lists are allowed. This way we can construct two-dimensional data structures.

    a = [[3, 4, 5], [-3, 7, 2], [4, 7, 5]]

    print(a[0])

    print(a[0][0], a[2][0])

    [3, 4, 5]
    3 4

Items of a list can be modified after creation of the list:

    a = [3, 4, 5]
    print(a)

    a[1] = 1000
    print(a)

    [3, 4, 5]
    [3, 1000, 5]

How to append elements to an existing list and many more list related topics will be discussed later on.

Note

A list may have length 0, that is, it may be empty. Empty lists occur frequently because often one wants to fill lists item by item, starting with an empty list. To get an empty list in Python write `[]`.

## Make a Building from Building Blocks

With the above building blocks at hand we may write arbitrarily complex programs. There is nothing more we need. It’s like Lego blocks. Take lots of simple blocks, add some creativity, and think about how to reach your aim step by step.

All the other features of Python we’ll discuss soon only exist to simplify programming, save some time and make programs more readable. But they won’t add new possibilities.

Building everything from scratch is a long and winding road. So we’ll use other people’s code and combine it to new and larger projects. There’s a large library of ready-to-use code snippets, called the Python standard library. For specific tasks like data science and AI there are specialized libraries containg thousands of functions we may use without implementing them ourselves. Examples are Matplotlib, Pandas, Scikit-Learn and Tensorflow.