#!/usr/bin/env python # coding: utf-8 # # **PART 1: PYTHON - A (VERY) SHORT INTRODUCTION** # Today you'll learn the basics of programming in Python. We are currently using a so-called **Python notebook**. The notebook consists of two types of cells, those that contain text (like the one you're reading right now) and those that contain Python code. # # Below is an example of a cell with Python code. When we click on a cell with code and either press [SHIFT] + [ENTER] or click on the [RUN] button above, we tell the computer to interpret the commands which means that it turns the Python code into actions we want it to execute. # In[ ]: # This is a comment. Everything preceeded by a hash symbol (#) is ignored by the computer. # This allows you to add comments/notes/documentation to your Python programme. print("Hello world") # As you can see, we instructed the computer to "print" a string of letters. # # Don't worry too much about the syntax right now, we'll go through this step by step. # ___ # ## **1.1 VARIABLES** # Variables are used to store information that can later be referenced and manipulated by your computer program. It's helpful to think of variables as containers for information. For example, imagine you build a drawer and put socks in it. In this case, the drawer would be a variable and the socks we put in would correspond to its value(s). When you reference the variable, i.e. open the drawer, you'll find socks in there. # In[ ]: # Let's create a drawer with socks drawer = "socks" # Let's have a look what's inside the drawer drawer # Variables would be useless if you couldn't assign values to them. Python is able to handle all sorts of different datatypes, such as numbers, strings (= sequences of letters and symbols) and lists of numbers/letters. Below are a few examples: # # # # ### **1.1.1 Assign values to variables** # In[ ]: # This is an integer (a number without any decimal points) variable1 = 5 # This is another integer variable2 = 7 # This is a float (a number with decimal points) variable3 = -2.563 # This is a string (a sequences of characters) variable4 = 'Hello World' # This is a list (a set of different items) variable5 = [1,2, 'Tomato',0,'???'] # Let's check out what's inside these variables: # In[ ]: variable5 # **IMPORTANT!** # # Variable names are somewhat arbitrary, but try to give your variables sensible names that explain what kind of information they hold (remember the drawer example above). This prevents a lot of confusion when you come back to code you wrote weeks or months ago! # # Also, there a few general rules for naming variables. # # 1. Variable names shouldn't start with a **number**. # 2. Variable names shouldn't start with a **special symbol** (e.g. $ or ^). # In[ ]: # See what happens when you try to give your variable an invalid name. ^my_var = 12 # ### **1.1.2 Operations using defined variables** # # What makes programming languages so powerful is their ability to perform various operations on the variables you have defined. In this section, you'll learn a few of those! # #### **Basic addition & subtraction** # Let's write a program that adds two of the variables we have defined above: # In[ ]: variable1 + variable2 # You can conduct basic math directly in-line, but if you need more than one operation to run, you'll want to assign them to variables: # # In[ ]: sum_of_two = variable1 + variable2 difference = variable1 - variable2 difference2 = difference - variable3 # Notice how the results of these operations were not automatically displayed in the command line. This is desired behaviour of any programming language. Imagine that you have a very long and complicated script full of mathematical operations, but are only interested in the end result. It would be a nightmare if each and every intermediate result was displayed in the command line. # To display specific variables (and some text) in the command line, use the **print** statement. # # The print statement is a **function**. As in maths, functions take some value as input, apply a transformation and return the result of this transformation as output. In case of the print statement, it takes strings of characters and variables as input, and - as the name suggests - "prints" the result to the command line (in our case the space below a cell with Python code). We'll learn more about functions later in the course. # As you can see in the example below, the print function accepts all sorts of different input formats. Choose the one that works best for you! # In[ ]: # One variable print(difference2) # Multiple variables can be separated by a comma print(sum_of_two, difference) # We can also construct a string by concatenating text and numbers (that we have turned into strings using the str() function) print('Sum of int1 and int2 is ' + str(sum_of_two) + ' and difference between them is ' + str(difference)) # You can also use {} as placeholders and use the format method to feed values into the placeholders print('Sum of int1 and int2 is {}, and differene between them is {}'.format(sum_of_two, difference)) # In case you were confused: Python distinguishes between different types of variables. # If we assign a number to a variable, Python will assume that it's a number. # If we put that same number into quotation marks, it will assume it's a string (= letter on your keyboard) and can't do maths with it. # "+" between numbers adds them up. "+" between strings concatenates them. # In[ ]: five_num = 5 five_str = '5' # This is equal to str(five_num) one_num = 1 one_str = '1' print(five_num + one_num) print(five_str + one_str) print(five_num + five_str) # #### **Basic multiplication and division** # # Imagine how limited a programming language would be if you couldn't perform multiplication and division. Luckily, Python has you covered! # In[ ]: int1 = 20 int2 = 6 product_of_two = int1 * int2 quotient_of_two = int1 / int2 modulo_of_two = int1 % int2 print('Product of int1 and int2 is {}'.format(product_of_two)) print('Dividing int1 by int2 yields {} '.format(quotient_of_two)) print('The remainder after dividing int1 by int2 is {} '.format(modulo_of_two)) # **Exponentiation** # # Exponentiation of numbers follows a very simple syntax, too! # # In[ ]: base = 5 exponent = 2 result = base**exponent expr = r'${base}^{exponent}$' print("{base} to the power of {exponent} (i.e. {base}^{exponent}) is {result}".format(base=base,exponent=exponent,result=result,expr=expr)) # **Square root** # # Maybe you remember from your maths lectures that the square root can be expressed as follows: # $$\sqrt{x} = x^{0.5}$$ # We can therefore easily compute square roots using what we've learned about exponentiation! # In[ ]: int1 = 256 sqroot = int1**0.5 print('The square root of {} is {}'.format(int1,sqroot)) # #### **Logical operators** # In programming you very often need to know whether some statement is true or false. This can be achieved with so-called **Boolean variables**, which you'll find very handy over time: # In[ ]: bool1 = True bool2 = False print(bool1) print(bool2) print(bool1 and bool2) print(bool1 or bool2) print(bool1 and not bool2) # In[ ]: numBelow10 = [1,2,3,4,5,6,7,8,9] demonstrators = 'Timo & Jelka' print(11 in numBelow10) # Check whether number 11 is in the previously defined variable 'numBelow10' print('a' in demonstrators) # Check if any of the demonstators have letter 'a' in their names # In[ ]: # Boolean variables also have their numerical value. Check the value of 'True' and 'False' in the code below. print(True == 1) print(False == 0) # Most frequently, you will be able to check whether relationships between variables are true or false or do something conditionally based on whether a statement is true (see below): # In[ ]: print(5 < 6) print(6 >= 5) print(5 != 10/2) print('hello' != 'world') # Logical operators are very powerful. For instance, you can test whether a variable lies within a certain interval: # In[ ]: int1 = 10 print(int1 < 12 and int1 > 9) print( 9 < int1 < 12) # ### **TASK 1:** # # 1. Open a new Python code cell below # 2. Calculate the square root of 144 and save it to a variable 'sqroot144'. # 3. Define a string variable that will contain your name and check if you have letter 'i' in your name. # 4. Assign any 3 numbers (between 1 and 100) to 3 different variables. After doing that, add up your 3 variables, check whether their sum is between 100 and 120 and print the result # 5. Check the type of each of the variables you defined by using the function type(). # # # In[ ]: # Type your code below: # ___ # ## **1.2 LOOPS AND STATEMENTS** # Loops allow you to execute the same operation multiple times, but with a different type of input on each iteration. # Statement allow you to structure your code, and have the computer care about certain bits only if conditions you specify are met. # In this section, we'll learn more about both. # ### **1.2.1 While loops** # Use while loops whenever you need to apply an operation multiple times, but don't know exactly how many iterations are needed: # In[ ]: # Example of a while loop x = 500 while x > 10: print(str(x)) x = x // 2 # ### **1.2.2 For loops** # For loops come in handy whenever you need to apply a function to each item of a # (potentially very long) list, and you know exactly how many iterations you need: # # In[ ]: # Example of a for loop modules = ["cognitive", "developmental", "neuro", "clinical", "social", "computational"] for x in modules: print(x) # For loops can also iterate over a sequence of numbers using the "range" function. for x in range(5): # A sequence starts with 0 and ends with 4! print(x) # Python 'counts' from 0 and ignores the last number specified by range. for example, range(0,5) will print the numbers from 0 to 4 # ### **1.2.3 If-then conditionals** # Before we talk about if-then conditionals, let's first learn something new: the **len()** command counts the number of symbols in a list. # # Example: # # In[ ]: # Let's count how many numbers are in this list print(len([4,5,5,2,1])) # Note that it also works with strings (which are essentially lists of symbols) print(len('hello world')) # Programming is all about case-specific processing. # # Use if-then statements # to process inputs depending on conditions you have specified: # In[ ]: # Example of a if-then statement favoriteModule = "computational" firstModule = "social" if len(firstModule) != len(favoriteModule): print('These modules are of different lengths!') elif len(firstModule) == len(favoriteModule): print('These modules are of same lengths!') # Based on what you have seen so far, what is the difference between = and == in Python? # Very often you'll find that you want to check multiple conditions before doing something with your variables. You can do this by using logical connectors such as 'and' or 'or'. # In[ ]: a = 60 b = 30 c = 70 if a > b and c > a: print('Both conditions are true!') elif a > b or c > a: print('At least one of the conditions is true!') else: print('Both conditions are not true!') # ### **TASK 2:** # # Write your own loops. # # Given: # # ``` # modules = ["cognitive", "developmental", "neuro", "clinical", "social", "computational"] # comparisonVariable = "introductory" # ``` # # Determine whether any of the modules have names that are longer than the comparison variable. # In[ ]: modules = ["cognitive", "developmental", "neuro", "clinical", "social", "computational"] comparisonVariable = "introductory" # Type your code below: # ___ # ## **1.3 FUNCTIONS** # # ### **1.3.1 Introduction to functions** # Functions are nothing new. You have already worked with them in the previous exercises and we've learned that they usually take some input and apply a transformation to it. # # Here are some examples... # # # In[ ]: print("hello world") print("2*3:",2*3) print(len("hello world")) # What makes coding so great is that you're able to write your own functions! Whenever you identify a recurring task in your workflow, consider writing a function instead of copying and pasting the code over and over again: # In[ ]: # Naive approach for testing parity of several numbers (i.e. whether they are odd or even): if 3 % 2 == 0: print('{} is even'.format(3)) else: print('{} is odd'.format(3)) if 2 % 2 == 0: print('{} is even'.format(2)) else: print('{} is odd'.format(2)) if 11 % 2 == 0: print('{} is even'.format(11)) else: print('{} is odd'.format(11)) # In the example above, we tested whether several numbers are odd or even. # Instead of repeating the same thing over and over again, we can put it in a neat little function: # In[ ]: # Let's write a function that does the work for us! def return_parity(n): result = str(n) + ' is' if n % 2 == 0: return result + ' even' else: return result + ' odd' # Now we can simply apply the function to each of the numbers we're interested in. # In[ ]: print(return_parity(3)) print(return_parity(2)) print(return_parity(11)) # By the way, if-else statements can be compressed into one-liners: # In[ ]: # Let's make this shorter def return_parity(n): result = str(n) + ' is ' return result + 'even' if n % 2 == 0 else result + 'odd' # Did you notice something? We applied the function to several different numbers. # Why not put all numbers in a list and use a loop to iterate over them? # In[ ]: # Let's combine this with loops numbers = [3, 2, 11] for num in numbers: print(return_parity(num)) # Functions can be put inside other functions. Let's write a wrapper that iterates over a list! # In[ ]: #let's write a wrapper! def check_item_parity(arr): for ii in arr: print(return_parity(ii)) # In[ ]: check_item_parity(numbers) # ### **1.3.2 Docstrings** # Programming can be a very complicated endeavour. # Who is able to remember each and every function and how to use it? **Nobody.** # # In fact, in real life, whenever you need to write a program, you'll notice that you spend most of the time Googling stuff and scrolling through online forums. That's absolutely normal and even the biggest coding pros do this all the time. # But even if you don't have internet, there's still hope: Python provides documentation for all of its built-in functions. These brief info snippets are called **docstrings** and now, you will learn two ways to access them. # # First, you could simply add a question mark to the function you're interested in, and execute the line of code: # In[ ]: get_ipython().run_line_magic('pinfo', 'print') # Docstring: # print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False) # # Prints the values to a stream, or to sys.stdout by default. # Optional keyword arguments: # file: a file-like object (stream); defaults to the current sys.stdout. # sep: string inserted between values, default a space. # end: string appended after the last value, default a newline. # flush: whether to forcibly flush the stream. # Type: builtin_function_or_method # Alternatively, you pass it as argument to the help function: # In[ ]: help(print) # **When you write your own functions, don't forget to add documentation on how to use them.** # # This saves a lot of time and avoids nervous breakdowns when you come back to your code a few months later. # In fact, you can easily write your own docstrings! Here's an example: # In[ ]: def return_parity(n): """ This function tests whether its input is odd or even. INPUT: (int) an arbitrary number OUTPUT: (str) 'even' or 'odd' """ result = str(n) + ' is ' return result + 'even' if n % 2 == 0 else result + 'odd' # In[ ]: help(return_parity) # ### **TASK 3:** # Write a function that takes a list of numbers as input and returns the **mean** of these numbers. # # Remember, given a vector of numbers # > $\textbf{x} = [x_1, x_2, x_3, x_4, ...., x_n]$ # # the mean is defined as: # # > $mean(\textbf{x})=\frac{1}{N}\sum_{i=1}^{N} x_i = \frac{1}{N}(x_1 + x_2 + x_3 + ... + x_n)$ # # **Don't forget to add docstrings to your function!** # # In[ ]: numbers = [2,5,8,7,1,4,4,9] # Type your code below: # ___ # ## **1.4 .METHODS()** # Python is an object-oriented language. An object is an abstract entity that contains # some data and functions that can be applied to the data (Imagine a drawer (container) for socks (data) that has a built-in sock sorting machine (function)). Functions that are applied directly to objects are called **methods**. In this section we'll learn how to apply methods to objects. # # # Many entities in Python are objects. For example, strings are objects as they contain some data, as for example "hello world", and they come with many methods that can be applied to the data. # # Let's have a look at an example: # ### **1.4.1 Example: Methods to manipulate strings** # In[ ]: # First, we create a simple variable that contains a sequence of symbols string = "hello world" # Python understands that this is a string, and allows you to apply methods # that are purpose-built for string manipulation: print(string.upper()) print(string.capitalize()) print(string.replace(' world',', nice to meet you')) listOfWords = string.split(' ') print(listOfWords) newString = ', '.join(listOfWords) print(newString) # In contrast to functions, for which the syntax is **function(argument)**, methods are bound to objects. Thus, the syntax is **object.method(argument)**. # ### **1.4.2 Methods are object specific!** # As methods are bound to a particular object type, you can't apply them to other objects. For instance, you can't capitalise numbers: # In[ ]: # Let's create a variable that contains a number number = 0.5 # Python realises that this is not a string, and therefore you're not able to capitalise it! number.capitalize() # ### **1.4.3 How to figure out which methods are provided for a given object?** # To see a list of all available methods, either press [TAB] after placing a dot behind an object, or use the following syntax: # In[ ]: dir(str) # In[ ]: help(str.split) # ### **TASK 4**: # # You're given the following string: # # ```python # sentence = 'Michaelmas term starts in October.' # ``` # # 1. Write a function that puts all vowels in the upper case, while all the consonants stay in the lower case. Test your function on the variable 'sentence'. # # 2. Create a new variable where the word 'Michaelmas' will be replaced with the word 'Trinity' and 'October' with 'April'. # In[ ]: sentence = 'Michaelmas term starts in October.' # Type your code below: # **Congratulations, you made it to the end of part 1!** # # Let's now continue with part 2, where we'll show you how to use packages to enhance the functionality of Python, and how to use Python like a scientist!