Python the essentials: A minimal introduction

Introduction to GIS scripting
May, 2017

© 2017, Stijn Van Hoey (mailto:stijnvanhoey@gmail.com). Licensed under CC BY 4.0 Creative Commons

First steps

the obligatory...


In [131]:
print("Hello INBO_course!") # python 3(!)


Hello INBO_course!

Python is a calculator


In [27]:
4*5


Out[27]:
20

In [28]:
3**2


Out[28]:
9

In [29]:
(3 + 4)/2, 3 + 4/2,


Out[29]:
(3.5, 5.0)

In [30]:
21//5, 21%5  # floor division, modulo


Out[30]:
(4, 1)

also logical operators:


In [2]:
3 > 4, 3 != 4, 3 == 4


Out[2]:
(False, True, False)

Variable assignment


In [6]:
my_variable_name = 'DS_course'
my_variable_name


Out[6]:
'DS_course'

In [7]:
name, age = 'John', 30
print('The age of {} is {:d}'.format(name, age))


The age of John is 30

More information on print format: https://pyformat.info/

REMEMBER:

  • Use relevant variable names, e.g. `name` instead of `n`
  • Keep variable names lowercase, with underscore for clarity, e.g. `darwin_core` instead of `DarwinCore`
  • Loading functionalities

    
    
    In [31]:
    import os
    
    R comparison:

    You would load a library (`library("ggplot2")`) instead of importing a package

    
    
    In [32]:
    os.listdir()
    
    
    
    
    Out[32]:
    ['00-jupyter_introduction.ipynb',
     '01-python-introduction.ipynb',
     '.ipynb_checkpoints',
     '__pycache__']

    Loading with defined short name (community agreement)

    
    
    In [33]:
    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    

    Loading functions from any file/module/package:

    
    
    In [34]:
    %%file rehears1.py  
    #this writes a file in your directory, check it(!)
    
    "A demo module."
    
    def print_it():
        """Dummy function to print the string it"""
        print('it')
    
    
    
    
    Writing rehears1.py
    
    
    
    In [35]:
    import rehears1
    
    
    
    In [36]:
    rehears1.print_it()
    
    
    
    
    it
    
    
    
    In [37]:
    %%file rehears2.py  
    #this writes a file in your directory, check it(!)
    
    "A demo module."
    
    def print_it():
        """Dummy function to print the string it"""
        print('it')
    
    def print_custom(my_input):
        """Dummy function to print the string that"""
        print(my_input)
    
    
    
    
    Writing rehears2.py
    
    
    
    In [38]:
    from rehears2 import print_it, print_custom
    
    
    
    In [39]:
    print_custom('DS_course')
    
    
    
    
    DS_course
    
    REMEMBER:

    Importing **packages** is always the first thing you do in python, since it offers the functionalities to work with!

    Different options are available:

    • import package-name
      importing all functionalities as such
    • from package-name import specific function
      importing a specific function or subset of the package
    • import package-name as short-package-name
      Very good way to keep a good insight in where you use what package
    DON'T: `from os import *`. Just don't!

    Datatypes

    Numerical

    floats

    
    
    In [40]:
    a_float = 5.
    
    
    
    In [41]:
    type(a_float)
    
    
    
    
    Out[41]:
    float

    integers

    
    
    In [42]:
    an_integer = 4
    
    
    
    In [43]:
    type(an_integer)
    
    
    
    
    Out[43]:
    int

    booleans

    
    
    In [44]:
    a_boolean = True
    a_boolean
    
    
    
    
    Out[44]:
    True
    
    
    In [45]:
    type(a_boolean)
    
    
    
    
    Out[45]:
    bool
    
    
    In [46]:
    3 > 4 # results in boolean
    
    
    
    
    Out[46]:
    False
    R comparison:

    Booleans are written as False or True, NOT as FALSE/TRUE

    
    
    In [132]:
    print(False) # test yourself with FALSE
    
    
    
    
    False
    

    Containers

    Strings

    
    
    In [28]:
    a_string = "abcde"
    a_string
    
    
    
    
    Out[28]:
    'abcde'

    A string is a collection of characters...

    
    
    In [29]:
    a_string.capitalize(), a_string.upper(), a_string.endswith('f') # Check the other available methods for a_string yourself!
    
    
    
    
    Out[29]:
    ('Abcde', 'ABCDE', False)
    
    
    In [30]:
    a_string.upper().replace('B', 'A')
    
    
    
    
    Out[30]:
    'AACDE'
    
    
    In [31]:
    a_string + a_string
    
    
    
    
    Out[31]:
    'abcdeabcde'
    
    
    In [32]:
    a_string * 5
    
    
    
    
    Out[32]:
    'abcdeabcdeabcdeabcdeabcde'

    Lists

    A list can contain mixed data types (character, float, int, other lists,...)

    
    
    In [51]:
    a_list = [1, 'a', 3, 4]
    a_list
    
    
    
    
    Out[51]:
    [1, 'a', 3, 4]
    
    
    In [53]:
    another_list = [1, 'a', 8.2, 4, ['z', 'y']]
    another_list
    
    
    
    
    Out[53]:
    [1, 'a', 8.2, 4, ['z', 'y']]
    
    
    In [34]:
    a_list.append(8.2)
    a_list
    
    
    
    
    Out[34]:
    [1, 'a', 3, 4, 8.2]
    
    
    In [35]:
    a_list.reverse()
    a_list
    
    
    
    
    Out[35]:
    [8.2, 4, 3, 'a', 1]
    REMEMBER:

    The list is updated in-place; a_list.reverse() does not return anything, it updates the list
    
    
    In [146]:
    a_list + ['b', 5]
    
    
    
    
    Out[146]:
    [8.2, 4, 3, 'a', 1, 'b', 5]

    ADVANCED users area: list comprehensions

    
    
    In [79]:
    [el*2 for el in a_list]  # list comprehensions...a short for-loop
    
    
    
    
    Out[79]:
    [16.4, 8, 6, 'aa', 2]

    list comprehensions are basically a short-handed version of a for-loop inside a list. Hence, the previous action is similar to:

    
    
    In [80]:
    new_list = []
    for element in a_list:
        new_list.append(element*2)
    print(new_list)
    
    
    
    
    [16.4, 8, 6, 'aa', 2]
    

    Another example checks the methods available for the list data type:

    
    
    In [81]:
    [el for el in dir(list) if not el[0] == '_']
    
    
    
    
    Out[81]:
    ['append',
     'clear',
     'copy',
     'count',
     'extend',
     'index',
     'insert',
     'pop',
     'remove',
     'reverse',
     'sort']
    EXERCISE:
    • Rewrite the previous list comprehension by using a builtin string method to test if the element starts with an underscore
    
    
    In [75]:
    [el for el in dir(list) if not el.startswith('_')]
    
    
    
    
    Out[75]:
    ['append',
     'clear',
     'copy',
     'count',
     'extend',
     'index',
     'insert',
     'pop',
     'remove',
     'reverse',
     'sort']
    EXERCISE:
    • Given the sentence `the quick brown fox jumps over the lazy dog`, split the sentence in words and put all the word-lengths in a list.
    
    
    In [72]:
    sentence = "the quick brown fox jumps over the lazy dog"
    
    
    
    In [82]:
    #split in words and get word lengths
    [len(word) for word in sentence.split()]
    
    
    
    
    Out[82]:
    [3, 5, 5, 3, 5, 4, 3, 4, 3]

    R comparison:

    R also has lists as data type, e.g. `list(c(2, 5, 3), 21.3, "a")`

    Dictionary

    A dictionary is basically an efficient table that maps keys to values. It is an unordered container

    It can be used to conveniently store and retrieve values associated with a name

    
    
    In [133]:
    a_dict = {'a': 1, 'b': 2}
    
    
    
    In [134]:
    a_dict['c'] = 3
    a_dict['a'] = 5
    
    
    
    In [135]:
    a_dict
    
    
    
    
    Out[135]:
    {'a': 5, 'b': 2, 'c': 3}
    
    
    In [98]:
    a_dict.keys(), a_dict.values(), a_dict.items()
    
    
    
    
    Out[98]:
    (dict_keys(['b', 'a', 'c']),
     dict_values([2, 5, 3]),
     dict_items([('b', 2), ('a', 5), ('c', 3)]))
    
    
    In [99]:
    an_empty_dic = dict() # or just {}
    an_empty_dic
    
    
    
    
    Out[99]:
    {}
    
    
    In [100]:
    example_dict = {"timeseries": [2, 5, 3], 
                    "parameter": 21.3,
                    "scenario": "a"}
    example_dict
    
    
    
    
    Out[100]:
    {'parameter': 21.3, 'scenario': 'a', 'timeseries': [2, 5, 3]}
    R comparison:

    R also has a dictionary like data type, e.g.

    > example_dict <- list(c(2,5,3),21.3,"a")
    > names(example_dict) <- c("timeseries", "parameter", "scenario")
    > example_dict
    $timeseries
    [1] 2 5 3
    
    $parameter
    [1] 21.3
    
    $scenario
    [1] "a"
    

    Tuple

    
    
    In [101]:
    a_tuple = (1, 2, 4)
    
    REMEMBER:

    The type of brackets - (), [], {} - to use depends from the data type you want to create!
  • [] -> list
  • () -> tuple
  • {} -> dictionary
  • 
    
    In [136]:
    collect = a_list, a_dict
    
    
    
    In [137]:
    type(collect)
    
    
    
    
    Out[137]:
    tuple
    
    
    In [138]:
    serie_of_numbers = 3, 4, 5
    
    
    
    In [139]:
    # Using tuples on the left-hand side of assignment allows you to extract fields
    a, b, c = serie_of_numbers
    
    
    
    In [140]:
    print(c, b, a)
    
    
    
    
    5 4 3
    

    Accessing container values

    
    
    In [19]:
    grades = [88, 72, 93, 94]
    
    
    
    In [20]:
    from IPython.display import SVG, display
    display(SVG("../img/slicing-indexing.svg"))
    
    
    
    
    background Layer 1 grades = [88, 72, 93, 94] 0 1 3 indexing: getting a specific element >>> grades[2] 93 2
    
    
    In [21]:
    grades[2]
    
    
    
    
    Out[21]:
    93
    REMEMBER:
    • Python starts counting from 0 !
    
    
    In [22]:
    from IPython.display import SVG, display
    display(SVG("../img/slicing-slicing.svg"))
    
    
    
    
    background Layer 1 grades = [88, 72, 93, 94] 0 2 4 slicing: selecting a set of elements >>> grades[1:3] [72, 93] 1 3
    
    
    In [23]:
    grades[1:3]
    
    
    
    
    Out[23]:
    [72, 93]
    
    
    In [36]:
    a_list = [1, 'a', 8.2, 4]
    
    
    
    In [25]:
    a_list[0], a_list[2]
    
    
    
    
    Out[25]:
    (1, 8.2)

    Select from...till

    
    
    In [37]:
    a_string = "abcde"
    a_string
    
    
    
    
    Out[37]:
    'abcde'
    
    
    In [38]:
    a_string[2:4]
    
    
    
    
    Out[38]:
    'cd'

    Select, counting backward:

    
    
    In [39]:
    a_list[-2]
    
    
    
    
    Out[39]:
    8.2
    R comparison:

    The `-` symbol in R has a completely different meaning: `NOT`

    > test <- c(1, 2, 3, 4, 5, 6)
    > test[-2]
    [1] 1 3 4 5 6
    
    
    
    In [40]:
    a_list = [0, 1, 2, 3]
    

    From the first element until a given index:

    
    
    In [41]:
    a_list[:3]
    
    
    
    
    Out[41]:
    [0, 1, 2]
    
    
    In [42]:
    a_list[::2]
    
    
    
    
    Out[42]:
    [0, 2]

    Dictionaries

    
    
    In [45]:
    a_dict = {'a': 1, 'b': 2}
    a_dict['a']
    
    
    
    
    Out[45]:
    1

    Tuples

    
    
    In [46]:
    a_tuple = (1, 2, 4)
    a_tuple[1]
    
    
    
    
    Out[46]:
    2
    REMEMBER:
    • [] for accessing elements
    • Note that L[start:stop] contains the elements with indices i such as start <= i < stop
    • (i ranging from start to stop-1). Therefore, L[start:stop] has (stop-start) elements.
    • Slicing syntax: L[start:stop:stride]
    • all slicing parameters are optional

    Assigning new values to items -> mutable vs immutable

    
    
    In [47]:
    a_list
    
    
    
    
    Out[47]:
    [0, 1, 2, 3]
    
    
    In [48]:
    a_list[2] = 10 # element 2 changed -- mutable
    a_list
    
    
    
    
    Out[48]:
    [0, 1, 10, 3]
    
    
    In [49]:
    a_tuple[1] = 10 # cfr. a_string -- immutable
    a_string[3] = 'q'
    
    
    
    
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-49-eb7a02e1a0dd> in <module>()
    ----> 1 a_tuple[1] = 10 # cfr. a_string -- immutable
          2 a_string[3] = 'q'
    
    TypeError: 'tuple' object does not support item assignment

    Control flows (optional)

    for-loop

    
    
    In [169]:
    for i in [1, 2, 3, 4]:
        print(i)
    
    
    
    
    1
    2
    3
    4
    
    **Indentation** is VERY IMPORTANT in Python. Note that the second line in the example above is indented
    
    
    In [ ]:
    
    
    
    
    In [170]:
    for i in a_list: # anything that is a collection/container can be looped
        print(i)
    
    
    
    
    0
    1
    10
    3
    
    EXERCISE:
    • Loop through the characters of the string `Hello DS` and print each character separately within the loop
    
    
    In [172]:
    for char in 'Hello DS':
        print(char)
    
    
    
    
    H
    e
    l
    l
    o
     
    D
    S
    
    
    
    In [173]:
    for i in a_dict: # items, keys, values
        print(i)
    
    
    
    
    b
    a
    c
    
    
    
    In [174]:
    for j, key in enumerate(a_dict.keys()):
        print(j, key)
    
    
    
    
    0 b
    1 a
    2 c
    
    REMEMBER:

    When needing a iterator to count, just use `enumerate`. you mostly do not need i = 0 for... i = i +1.
    Check [itertools](http://pymotw.com/2/itertools/) as well...

    while

    
    
    In [175]:
    b = 7
    while b < 10:
        b+=1
        print(b)
    
    
    
    
    8
    9
    10
    

    if statement

    
    
    In [176]:
    if 'a' in a_dict:
        print('a is in!')
    
    
    
    
    a is in!
    
    
    
    In [177]:
    if 3 > 4:
        print('This is valid')
    
    
    
    In [178]:
    testvalue = False  # 0, 1, None, False, 4 > 3
    if testvalue:
        print('valid')
    else:
        raise Exception("Not valid!")
    
    
    
    
    ---------------------------------------------------------------------------
    Exception                                 Traceback (most recent call last)
    <ipython-input-178-197943eaf7cc> in <module>()
          3     print('valid')
          4 else:
    ----> 5     raise Exception("Not valid!")
    
    Exception: Not valid!
    
    
    In [179]:
    myvalue = 3
    if isinstance(myvalue, str):
        print('this is a string')
    elif isinstance(myvalue, float):
        print('this is a float')
    elif isinstance(myvalue, list):
        print('this is a list')
    else:
        print('no idea actually')
    
    
    
    
    no idea actually
    

    Functions

    We've been using functions the whole time...

    
    
    In [54]:
    len(a_list)
    
    
    
    
    Out[54]:
    4
    It is all about calling a **method/function** on an **object**!
    
    
    In [190]:
    a_list.reverse()
    a_list
    
    
    
    
    Out[190]:
    [0, 1, 10, 3]
    REMEMBER:

    Getting an overview of the available methods on the variable (i.e. object):

    Defining a function:

    
    
    In [193]:
    def custom_sum(a, b, verbose=False):
        """custom summation function
        
        Parameters
        ----------
        a : number
            first number to sum
        b : number
            second number to sum   
        verbose: boolean
            require additional information (True) or not (False)
        
        Returns
        -------
        my_sum : number
            sum of the provided two input elements
        """
        
        if verbose:
            print('print a lot of information to the user')
            
        my_sum = a + b    
        
        return my_sum
    

    Setup of a function:

    • definition starts with def
    • function body is indented
    • return keyword precedes returned value
    **Indentation** is VERY IMPORTANT in Python. Note that the second line in the example above is indented
    
    
    In [194]:
    custom_sum(2, 3, verbose=False)  # [3], '4'
    
    
    
    
    Out[194]:
    5
    EXERCISE:
    • Try **SHIFT-TAB** combination to read your own documentation!
    REMEMBER:

    () for calling functions!

    ADVANCED users area:

    Functions are objects as well... (!)

    
    
    In [184]:
    def f1():
        print('this is function 1 speaking...')
    
    def f2():
        print('this is function 2 speaking...')
    
    
    
    In [185]:
    def function_of_functions(inputfunction):
        return inputfunction()
    
    
    
    In [186]:
    function_of_functions(f1)
    
    
    
    
    this is function 1 speaking...
    

    Anonymous functions (lambda)

    
    
    In [187]:
    add_two = (lambda x: x + 2)
    
    
    
    In [188]:
    add_two(10)
    
    
    
    
    Out[188]:
    12

    Ready for some real Python power: Numpy/Pandas