{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "This is an introduction to Python workshop run by the Quantitative Sciences Course Union (QSCU) at the University of British Columbia, Okanagan Campus.\n", "\n", "The Intro to Python Workshop is run by Ivan Carvallho and Kathryn Lecha" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# A Beginner's Introduction" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Comments\n", "\n", "Comments are sections of code ignored by the computer and instead saved for developers to read. They are very important when maintaining long chunks of code that many developers will see.\n", "\n", "Documentation is a very important aspect of programming." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.050038Z", "start_time": "2020-01-29T00:17:02.045474Z" } }, "outputs": [], "source": [ "# this is a comment\n", "# the program will ignore comments\n", "# they are for developer use" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Simple Data Manipulation" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Variables" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Variables are used to store data. This is useful for both large amounts of data and data that has the possibility of changing.\n", "\n", "In practice, even if the data is not expected to change, it is saved as a variable, partially for readability.\n", "\n", "Variables should always be given descriptive names that follow the form:\n", "word1_word2_etc" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.063047Z", "start_time": "2020-01-29T00:17:02.056338Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ivan is 19 years old.\n" ] } ], "source": [ "name = \"Ivan\"\n", "age = 19\n", "\n", "print(name, \"is\", age, \"years old.\")" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.073375Z", "start_time": "2020-01-29T00:17:02.067259Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ivan is 20 years old.\n" ] } ], "source": [ "# suppose a year passes\n", "age = 20\n", "print(name, \"is\", age, \"years old.\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Arithmatic Operators\n", "Python has all of the standard arithmetic operators for mathematical operations." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.091864Z", "start_time": "2020-01-29T00:17:02.080713Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Math with 5 and 3\n", "Addition: 8\n", "Subtraction: 2\n", "Multiplication: 15\n", "Division: 1.6666666666666667\n", "Exponentional (x^y): 125\n", "Modulus: 2\n" ] } ], "source": [ "x = 5\n", "y = 3\n", "print(\"Math with 5 and 3\")\n", "\n", "add = x + y\n", "print(\"Addition:\", add)\n", "\n", "sub = x - y\n", "print(\"Subtraction:\", sub)\n", "\n", "mul = x * y\n", "print(\"Multiplication:\", mul)\n", "\n", "div = x / y\n", "print(\"Division:\", div)\n", "\n", "exp = x ** y\n", "print(\"Exponentional (x^y):\", exp)\n", "\n", "# modulus gets the remainder of x / y\n", "mod = x % y\n", "print(\"Modulus:\", mod)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also assign new values to variables based on mathematical operations" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.106682Z", "start_time": "2020-01-29T00:17:02.095677Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Before incrementing: 5\n", "After incrementing: 8 \n", "\n", "Before decrementing: 8\n", "After decrementing: 5 \n", "\n", "Before multication: 5\n", "After multication: 15 \n", "\n", "Before division: 15\n", "After division: 5.0\n" ] } ], "source": [ "# increment x by y\n", "# x = x + y\n", "print(\"Before incrementing:\", x)\n", "x += y\n", "print(\"After incrementing:\", x, '\\n')\n", "\n", "# decrement x by y\n", "# x = x - y\n", "print(\"Before decrementing:\", x)\n", "x -= y\n", "print(\"After decrementing:\", x, '\\n')\n", "\n", "# This also works for other operators\n", "print(\"Before multication:\", x)\n", "x *= y\n", "print(\"After multication:\", x, '\\n')\n", "\n", "print(\"Before division:\", x)\n", "x /= y\n", "print(\"After division:\", x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Basic Logic Operations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Comparisions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We use comparisons to run code that reflects dependencies based off of program and variable status. \n", "\n", "The most basic comparision is the the IF statement that executes one set of operations if a condition is true and another if the condition is false." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.118376Z", "start_time": "2020-01-29T00:17:02.109430Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Condition1 is True\n" ] } ], "source": [ "condition1 = True\n", "condition2 = False\n", "\n", "if condition1:\n", " print(\"Condition1 is True\")\n", "elif condition2:\n", " print(\"Condition1 is False, but Condition2 is True\")\n", "else:\n", " print(\"Both Condition1 and Condition2 are False\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can use if statements evaluate variable values" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.128399Z", "start_time": "2020-01-29T00:17:02.122820Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x > y\n" ] } ], "source": [ "x = 5\n", "y = 9\n", "\n", "x += 5\n", "\n", "if x < y:\n", " print(\"x < y\")\n", "elif x > y:\n", " print(\"x > y\")\n", "else:\n", " print(\"x == y\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Loops" ] }, { "cell_type": "markdown", "metadata": { "ExecuteTime": { "end_time": "2020-01-17T01:34:13.316192Z", "start_time": "2020-01-17T01:34:13.295803Z" } }, "source": [ "Loops are used to keep code flexible and manageable, so there is no chunks of copy-paste code.\n", "\n", "There are 2 main types of loops:\n", "while and for loops" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### While Loops" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "While loops will continue to run while a condition is true" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.140069Z", "start_time": "2020-01-29T00:17:02.131747Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n", "4\n", "5\n", "6\n", "7\n", "8\n", "9\n" ] } ], "source": [ "i = 1\n", "while i < 10:\n", " print(i)\n", " i += 1" ] }, { "cell_type": "markdown", "metadata": { "ExecuteTime": { "end_time": "2020-01-17T01:36:56.309986Z", "start_time": "2020-01-17T01:36:56.299066Z" } }, "source": [ "Be careful to not create an infinite loop" ] }, { "cell_type": "raw", "metadata": { "ExecuteTime": { "end_time": "2020-01-17T20:46:34.957610Z", "start_time": "2020-01-17T20:46:34.952786Z" } }, "source": [ "while True:\n", " print(\"DO NOT RUN ME!!!\")\n", " print(\"i will not stop!!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### For Loops" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For loops will iterate for a fixed number of times. In many ways, it is a short way to write a while loop" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.191866Z", "start_time": "2020-01-29T00:17:02.184203Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n", "4\n", "5\n", "6\n", "7\n", "8\n", "9\n" ] } ], "source": [ "for i in range(0,10):\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Recursion" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Recursion is a higher level concept using functions that call themselves for repition. They need a base case to act as a condition to stop recursing.\n", "The main idea is to break down problems into smaller problems in a divide-and-conquer manner.\n", "We will learn more about functions later in this workshop." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.205254Z", "start_time": "2020-01-29T00:17:02.197866Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5\n", "4\n", "3\n", "2\n", "1\n", "0\n" ] } ], "source": [ "def recursive_loop(number):\n", " if(number > 0):\n", " print(number)\n", " return recursive_loop(number - 1)\n", " else:\n", " print(number)\n", " return\n", "\n", "recursive_loop(5)" ] }, { "cell_type": "markdown", "metadata": { "ExecuteTime": { "end_time": "2020-01-17T01:26:30.514311Z", "start_time": "2020-01-17T01:26:30.500030Z" } }, "source": [ "## Iterables" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Iterables are a kind of data structure that are able to be iterated over.\n", "This means that they serve as a structure in memory that hold data that is logically related in some way. Each peice of information in the structure can be accessed one at a time." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Lists" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lists are the most basic set of data structure. Each element in a list can be accessed by it's index (where its located), or in order.\n", "\n", "Lists can hold any datatype" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.215854Z", "start_time": "2020-01-29T00:17:02.210014Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['i', 'am', 'stressed', 'for', 'my', 'cosc', 328, 'midterm']\n" ] } ], "source": [ "sample_list = ['i', 'am','stressed', 'for', 'my', 'cosc', 328, 'midterm']\n", "print(sample_list)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.228326Z", "start_time": "2020-01-29T00:17:02.221368Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "You can access elements by index\n", "Remember python indexes from zero to follow industry standards\n", "Element 6: 328\n" ] } ], "source": [ "print(\"You can access elements by index\")\n", "print(\"Remember python indexes from zero to follow industry standards\")\n", "print(\"Element 6:\", sample_list[6])" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.238506Z", "start_time": "2020-01-29T00:17:02.230996Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "You can also access elements in reverse with the '-' character\n", "Note this does not start from zero\n", "Element -2 328\n" ] } ], "source": [ "print(\"You can also access elements in reverse with the '-' character\")\n", "print(\"Note this does not start from zero\")\n", "print(\"Element -2\", sample_list[-2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Data in a list is mutable and can be changed." ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.249924Z", "start_time": "2020-01-29T00:17:02.242428Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The new class is COSC 320\n" ] } ], "source": [ "# Suppose I finish the COSC 328 midterm and instead become stressed about the 320 midterm\n", "sample_list[6] = 320\n", "print(\"The new class is COSC\", sample_list[6])" ] }, { "cell_type": "markdown", "metadata": { "ExecuteTime": { "end_time": "2020-01-17T01:47:00.840381Z", "start_time": "2020-01-17T01:47:00.833578Z" } }, "source": [ "You can add elements to a list with APPEND or EXTEND. " ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.260202Z", "start_time": "2020-01-29T00:17:02.253126Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['i', 'am', 'stressed', 'for', 'my', 'cosc', 320, 'midterm', 'and final']\n" ] } ], "source": [ "sample_list.append(\"and final\")\n", "print(sample_list)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There is a very important difference between APPEND and EXTEND.\n", "You can have a list as an element in a list.\n", "\n", "APPEND will add the list as an element in the list\n", "\n", "EXTEND will append every element in the list to the list." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.269714Z", "start_time": "2020-01-29T00:17:02.262526Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Append:\n", "['cat', 'dog', 'log', ['frog', 'bog']]\n", "['frog', 'bog']\n" ] } ], "source": [ "list_1 = ['cat', 'dog', 'log']\n", "list_2 = ['frog', 'bog']\n", "\n", "list_1.append(list_2)\n", "print(\"Append:\")\n", "print(list_1)\n", "print(list_1[3])" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.282232Z", "start_time": "2020-01-29T00:17:02.273311Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Extend:\n", "['cat', 'dog', 'log', 'frog', 'bog']\n", "frog\n" ] } ], "source": [ "list_1 = ['cat', 'dog', 'log']\n", "list_2 = ['frog', 'bog']\n", "\n", "list_1.extend(list_2)\n", "print(\"Extend:\")\n", "print(list_1)\n", "print(list_1[3])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Tuples" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A tuple is an immutable collection of indexed objects. They are used for data that will never change. One example of this is coordinates (x,y,z)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.292751Z", "start_time": "2020-01-29T00:17:02.285320Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('cosc', 328, 'should', 'stay', 'an', 'immutable', 'unit')\n", "Element 4: stay\n" ] } ], "source": [ "sample_tuple = ('cosc', 328, 'should', 'stay', 'an', 'immutable', 'unit')\n", "print(sample_tuple)\n", "print(\"Element 4:\", sample_tuple[3])" ] }, { "cell_type": "raw", "metadata": { "ExecuteTime": { "end_time": "2020-01-17T20:46:35.218913Z", "start_time": "2020-01-17T20:46:35.107064Z" } }, "source": [ "# this will raise an exception\n", "sample_tuple[1] = 320" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Sets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sets are based off of mathematical sets. They are a collection of non-repeating, non-indexed objects." ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.332750Z", "start_time": "2020-01-29T00:17:02.325545Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'in', 'deleted', 'set', 'a', 'duplicate', 'is'}\n" ] } ], "source": [ "sample_set = {'a', 'duplicate', 'in', 'a', 'set', 'is', 'deleted'}\n", "print(sample_set)" ] }, { "cell_type": "raw", "metadata": { "ExecuteTime": { "end_time": "2020-01-17T20:46:35.225449Z", "start_time": "2020-01-17T20:46:35.064Z" } }, "source": [ "# this will produce an error\n", "sample_set[1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Dictionaries" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dictionaries are unique mappings of a key to a value, so you are able to uniquely define the text. " ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.464178Z", "start_time": "2020-01-29T00:17:02.451311Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{1: 'one', 2: 'two', 3: 'three', 4: 'four'}\n", "my_dict[1]: one\n" ] } ], "source": [ "my_dict = {1:'one', 2:'two', 3:'three', 4:'four'}\n", "print(my_dict)\n", "print(\"my_dict[1]:\", my_dict[1])" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.482179Z", "start_time": "2020-01-29T00:17:02.475961Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5\n" ] } ], "source": [ "my_dict[\"five\"]=5\n", "print(my_dict[\"five\"])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Relationship between loops and Iterables" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can use loops to process the data in iterables." ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.497781Z", "start_time": "2020-01-29T00:17:02.491228Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "this\n", "is\n", "a\n", "list\n", ":)\n" ] } ], "source": [ "sample_list = ['this', 'is', 'a', 'list', ':)']\n", "for item in sample_list:\n", " print(item)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### List Comprehension" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "List comprehension is a concise way to create lists with a loop and if statements" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.519778Z", "start_time": "2020-01-29T00:17:02.511479Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, -2, -4, -6, -8, -10, -12]\n" ] } ], "source": [ "# list comprehension\n", "some_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]\n", "negative_evens = [-i for i in some_list if i % 2 == 0]\n", "print(negative_evens)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.536863Z", "start_time": "2020-01-29T00:17:02.530238Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, -2, -4, -6, -8, -10, -12]\n" ] } ], "source": [ "# the equivalent code without list comprehension\n", "negative_evens = []\n", "for i in some_list:\n", " if i % 2 == 0:\n", " negative_evens.append(-i)\n", "print(negative_evens)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Functions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A function is a set of code made to do a set of tasks and return the result. Functions are useful when you have a chunck of code that will be run multiple times, so the chunck only has to be written once.\n", "\n", "It increases readability and maintainablity of code.\n", "\n", "Functions take in parameters, that act as variables within the function, and return the result of the function." ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.546526Z", "start_time": "2020-01-29T00:17:02.540508Z" } }, "outputs": [], "source": [ "def example_fucntion(parameter1, parameter2):\n", " ''' i am a comment explaining what the function does '''\n", " variable = parameter1 + 10\n", " \n", " output = 0\n", " if variable > parameter2:\n", " for i in range(0, parameter2):\n", " output += (variable - i)\n", " else:\n", " output = parameter2\n", " \n", " return output" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Functions can be called within functions" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.559315Z", "start_time": "2020-01-29T00:17:02.553873Z" } }, "outputs": [], "source": [ "def function_in_fuction():\n", " # you can have a function in a function\n", " print('a=4, b=9, c=-10, d=9')\n", " sum = add_all(4,9,-10,9)\n", " print('the sum of a, b, c, d is', sum)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Optional Parameters" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In Python, there can be optional parameters passed in. These optional parameters will take in the value denoted in the assignment if no value is passed in to the function." ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.575523Z", "start_time": "2020-01-29T00:17:02.562394Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Passed in:\n", "10\n", "\n", "Not Passed in:\n", "6\n" ] } ], "source": [ "def add_all(a, b, c, d=0):\n", " # if d is not given into the function,\n", " # the value of d is zero by default\n", " return a + b + c + d\n", "\n", "print(\"Passed in:\")\n", "print(add_all(1,2,3,4))\n", "\n", "print(\"\\nNot Passed in:\")\n", "print(add_all(1,2,3))" ] }, { "cell_type": "raw", "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.675033Z", "start_time": "2020-01-29T00:17:02.580451Z" } }, "source": [ "# note that this will only work for parameters denoted as optional\n", "print(\"i will produce an error\")\n", "print(add_all(1,2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# An Introduction to Advanced Techniques" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "At this point we will switch to a less directed instruction style. This portion of the Workshop was created for programmers with some experience that simply want to experience the more high level experience of Python." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Object Oriented Programming" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can say that everything in life is an object that follows some blueprint for making items. These are Objects.\n", "\n", "Python is an Object-Oriented language. It follows all of the OOP rules that other languages would follow." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.678075Z", "start_time": "2020-01-29T00:17:02.565Z" } }, "outputs": [], "source": [ "# this is an example of an Object in Python\n", "\n", "\n", "class Robot:\n", " '''\n", " This is a Robot\n", " '''\n", " # this is a constructor\n", " def __init__(self, metal_type, ai=True):\n", " # this is how you declare an attribute (self.attribute)\n", " self.metal_type = metal_type\n", " self.ai=ai\n", " \n", " def do_robot_thing(self):\n", " # i am a function\n", " # you have to use self to access object methods\n", " self.spin()\n", " \n", " def spin(self):\n", " print(\"wee!!\")\n", "\n", "\n", "class SpecialRobot(Robot):\n", " '''\n", " This is a Robot that has been extended to have a special item\n", " the (Robot) denotes that this class extends Robot\n", " '''\n", " def __init__(self, metal_type, ai=True, special_item='love and affection'):\n", " super(Robot)\n", " self.special_item = special_item\n", " \n", " def use_special_item(self):\n", " return self.special_item\n", " \n", " def change_special_item(self):\n", " new_item = input('What is the Robot\\'s new item?')\n", " print(\"Changing Robot's item to\", new_item)\n", " self.special_item = new_item\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.680331Z", "start_time": "2020-01-29T00:17:02.578Z" } }, "outputs": [], "source": [ "# instanciating objects:\n", "robot_1 = Robot(\"aluminum\")\n", "robot_1.do_robot_thing()\n", "\n", "robot_2 = SpecialRobot(\"tin\", True, \"bat\")\n", "robot_2.do_robot_thing()\n", "robot_2.change_special_item()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Functions As Objects" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Functions in python are first class objects. This means that they can be passed as arguments to other functions, assigned to variables or even stored as elements in various data structures. The ability to perform the same operation on a list of elements is provided by a higher-order python function called map." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Installing Packages" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Installing packages in Python can be very frustrating. There are two major package management systems for python: pip and conda." ] }, { "cell_type": "raw", "metadata": { "ExecuteTime": { "end_time": "2020-01-17T23:54:52.399430Z", "start_time": "2020-01-17T20:46:35.360410Z" } }, "source": [ "# these will both install the pandas library\n", "! pip install pandas\n", "! conda install pandas" ] }, { "cell_type": "raw", "metadata": { "ExecuteTime": { "end_time": "2020-01-17T23:54:58.512967Z", "start_time": "2020-01-17T23:54:52.404248Z" } }, "source": [ "# you can check what you've installed\n", "! pip list\n", "! conda list" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You will need to import the library into your program in order to use it" ] }, { "cell_type": "raw", "metadata": { "ExecuteTime": { "end_time": "2020-01-18T00:00:57.595026Z", "start_time": "2020-01-18T00:00:55.468972Z" } }, "source": [ "import pandas" ] }, { "cell_type": "raw", "metadata": { "ExecuteTime": { "end_time": "2020-01-18T00:00:57.604154Z", "start_time": "2020-01-18T00:00:57.597751Z" } }, "source": [ "# you could also only import certain Objects and Funtions\n", "# this follows PEP8 standards\n", "from pandas import DataFrame" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Reading From an External API" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this portion, we will try to read in information from the Financial Modeling Prep open API. This is a free API that we will try to read in some of their data." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "More on Financial Modelling Prep:\n", "Financial Modeling Prep is a new concept that informs you about stock markets information (news, currencies and stock prices)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Financial Modelling Prep offers Documentation on how to access their API here:\n", "https://financialmodelingprep.com/developer/docs/" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:02.791196Z", "start_time": "2020-01-29T00:17:02.783036Z" } }, "outputs": [], "source": [ "from urllib.request import urlopen\n", "import json\n", "\n", "def get_jsonparsed_data(ticker):\n", " \"\"\"\n", " Receive the content of ``url``, parse it as JSON and return the object.\n", "\n", " Parameters\n", " ----------\n", " url : str\n", "\n", " Returns\n", " -------\n", " dict\n", " \"\"\"\n", " url = get_url(ticker)\n", " response = urlopen(url)\n", " data = response.read().decode(\"utf-8\")\n", " return json.loads(data)\n", "\n", "def get_url(ticker):\n", " url = 'https://financialmodelingprep.com/api/financials/income-statement/' + ticker + '?datatype=json'\n", " return url" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:03.270624Z", "start_time": "2020-01-29T00:17:02.796012Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "JSON:\n", "{'FB': {'Revenue': {'2014-12': '12466', '2015-12': '17928', '2016-12': '27638', '2017-12': '40653', '2018-12': '55838', 'TTM': '55838'}, 'Cost of revenue': {'2014-12': '2153', '2015-12': '2867', '2016-12': '3789', '2017-12': '5454', '2018-12': '9355', 'TTM': '9355'}, 'Gross profit': {'2014-12': '10313', '2015-12': '15061', '2016-12': '23849', '2017-12': '35199', '2018-12': '46483', 'TTM': '46483'}, 'Research and development': {'2014-12': '2666', '2015-12': '4816', '2016-12': '5919', '2017-12': '7754', '2018-12': '10273', 'TTM': '10273'}, 'Sales, General and administrative': {'2014-12': '2653', '2015-12': '4020', '2016-12': '5503', '2017-12': '7242', '2018-12': '11297', 'TTM': '11297'}, 'Total operating expenses': {'2014-12': '5319', '2015-12': '8836', '2016-12': '11422', '2017-12': '14996', '2018-12': '21570', 'TTM': '21570'}, 'Operating income': {'2014-12': '4994', '2015-12': '6225', '2016-12': '12427', '2017-12': '20203', '2018-12': '24913', 'TTM': '24913'}, 'Interest Expense': {'2014-12': '23', '2015-12': '23', '2016-12': '10', '2017-12': '6', '2018-12': '9', 'TTM': '9'}, 'Other income (expense)': {'2014-12': '-61', '2015-12': '-8', '2016-12': '101', '2017-12': '397', '2018-12': '457', 'TTM': '457'}, 'Income before taxes': {'2014-12': '4910', '2015-12': '6194', '2016-12': '12518', '2017-12': '20594', '2018-12': '25361', 'TTM': '25361'}, 'Provision for income taxes': {'2014-12': '1970', '2015-12': '2506', '2016-12': '2301', '2017-12': '4660', '2018-12': '3249', 'TTM': '3249'}, 'Net income from continuing operations': {'2014-12': '2940', '2015-12': '3688', '2016-12': '10217', '2017-12': '15934', '2018-12': '22112', 'TTM': '22112'}, 'Net income': {'2014-12': '2940', '2015-12': '3688', '2016-12': '10217', '2017-12': '15934', '2018-12': '22112', 'TTM': '22112'}, 'Preferred dividend': {'2014-12': '15', '2015-12': '19', '2016-12': '29', '2017-12': '14', '2018-12': '1', 'TTM': '1'}, 'Net income available to common shareholders': {'2014-12': '2925', '2015-12': '3669', '2016-12': '10188', '2017-12': '15920', '2018-12': '22111', 'TTM': '22111'}, 'Basic': {'2014-12': '2614', '2015-12': '2803', '2016-12': '2863', '2017-12': '2901', '2018-12': '2890', 'TTM': '2890'}, 'Diluted': {'2014-12': '2664', '2015-12': '2853', '2016-12': '2925', '2017-12': '2956', '2018-12': '2921', 'TTM': '2921'}, 'EBITDA': {'2014-12': '6176', '2015-12': '8162', '2016-12': '14870', '2017-12': '23625', '2018-12': '29685', 'TTM': '29685'}}}\n" ] } ], "source": [ "ticker = 'FB'\n", "\n", "print(\"JSON:\")\n", "data = get_jsonparsed_data(ticker)\n", "print(data)" ] }, { "cell_type": "raw", "metadata": { "ExecuteTime": { "end_time": "2020-01-18T00:00:58.536384Z", "start_time": "2020-01-18T00:00:58.122470Z" } }, "source": [ "from pandas import DataFrame\n", "\n", "def get_company_dataframe(ticker):\n", " '''\n", " this is just a bonus :)\n", " '''\n", " data = get_jsonparsed_data(ticker)\n", " df = DataFrame(data[ticker])\n", " return df\n", "\n", "\n", "print('\\nthat\\'s hard to read... let\\'s try a dataframe:')\n", "data = get_company_dataframe(ticker)\n", "data.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Quality Shop of Coffee for University-Students (QSCU)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's build a small program for the following problem:\n", "\n", "Your friend works for the Quality Shop of Coffee for University-students (QSCU).\n", "\n", "The shop sells many types of drinks to customers, but does not know which one is the most popular! Can you help your friend keep track of the most sold item?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Modelling the Problem" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Necessary Elements:\n", "- We need a table to store our data \n", "- We need to be able to change the table to reflect sales\n", "- We need to find the most sold item\n", "\n", "What we will use:\n", "- SQLite, a small database contained in a file\n", "- Python with API to connect to SQLite" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Conneting to a Database" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In order to connect to a Database we need to create a connection and then create a cursor to execute our queries" ] }, { "cell_type": "raw", "metadata": {}, "source": [ "import sqlite3\n", "\n", "self.conn = sqlite3.connect(filename)\n", "self.cursor = self.conn.cursor()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Executing Queries" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Cursor has an execute method that may return rows from the database.\n", "Connection has a commit method to send changes to server." ] }, { "cell_type": "raw", "metadata": {}, "source": [ "self.cursor.execute(\n", " \"\"\"\n", " CREATE TABLE sales(\n", " name text,\n", " product_id int,\n", " price int,\n", " sold int\n", " ) \n", " \"\"\"\n", ")\n", "\n", "self.cursor.execute(\"\"\"INSERT INTO sales VALUES ('Espresso', 1, 2, 0)\"\"\")\n", "self.cursor.execute(\"\"\"INSERT INTO sales VALUES ('Macchiato', 2, 3, 0)\"\"\")\n", "self.cursor.execute(\"\"\"INSERT INTO sales VALUES ('Regular Java', 3, 1, 0)\"\"\")\n", "\n", "self.conn.commit()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Completing a Program" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's use what we discussed in the workshop to make a program for the QSCU.\n", "\n", "Below is a sample solution:" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:03.284361Z", "start_time": "2020-01-29T00:17:03.273742Z" } }, "outputs": [], "source": [ "import sqlite3\n", "\n", "\n", "class QSCU:\n", " \"\"\"Class representing the coffee shop, the interface to access the data.\"\"\"\n", "\n", " def __init__(self, filename):\n", " \"\"\"\n", " :param filename: the file that contains the SQLite DB.\n", " :type filename: string\n", " \"\"\"\n", "\n", " self.conn = sqlite3.connect(filename)\n", " self.cursor = self.conn.cursor()\n", " self.closed = False\n", "\n", " def setup_db(self):\n", " \"\"\"This function initializes the database. \n", " It creates the sales tables and inserts the coffe types that are sold.\n", " \n", " The database consists of 1 table:\n", " - sales table: a table listing all the coffees, their prices and their sales\n", " \"\"\"\n", "\n", " self.cursor.execute(\n", " \"\"\"\n", " CREATE TABLE sales(\n", " name text,\n", " product_id int,\n", " price int,\n", " sold int\n", " ) \n", " \"\"\"\n", " )\n", "\n", " self.cursor.execute(\"\"\"INSERT INTO sales VALUES ('Espresso', 1, 2, 0)\"\"\")\n", " self.cursor.execute(\"\"\"INSERT INTO sales VALUES ('Macchiato', 2, 3, 0)\"\"\")\n", " self.cursor.execute(\"\"\"INSERT INTO sales VALUES ('Regular Java', 3, 1, 0)\"\"\")\n", "\n", " self.conn.commit()\n", "\n", " def sell_item(self, product_id, quantity):\n", " \"\"\"Tells the database that a product was sold.\n", " :param product_id: the identification of the product that was sold\n", " :type product_id: int\n", " :param quantity: how many items were sold\n", " :type quantity: int\n", " \"\"\"\n", "\n", " self.cursor.execute(\n", " \"\"\"\n", " UPDATE sales \n", " SET sold = sold + $1\n", " WHERE product_id = $2\n", " \"\"\",\n", " [quantity, product_id],\n", " )\n", "\n", " self.conn.commit()\n", "\n", " def get_most_sold(self):\n", " \"\"\"Retrieve the most sold item of the coffe shop.\n", " :returns: list[(string, int)]\n", " \"\"\"\n", "\n", " most_sold_row = self.cursor.execute(\n", " \"\"\"\n", " SELECT name, sold\n", " FROM sales\n", " ORDER BY sold DESC\n", " LIMIT 1\n", " \"\"\"\n", " )\n", "\n", " return list(most_sold_row)[0]\n", "\n", " def close(self):\n", " \"\"\"Close connection to database\"\"\"\n", " self.cursor.close()\n", " self.conn.close()\n", " self.closed = True\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Unit Testing" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Unit testing is a way to test every function in code to see if any aspect of it is broken." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### The Hello World of Unit Testing" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:03.318949Z", "start_time": "2020-01-29T00:17:03.289822Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "test_add (__main__.TestAdd) ... ok\n", "\n", "----------------------------------------------------------------------\n", "Ran 1 test in 0.001s\n", "\n", "OK\n" ] } ], "source": [ "import unittest\n", "\n", "\n", "def add(x, y):\n", " return x + y\n", "\n", "\n", "class TestAdd(unittest.TestCase):\n", " def test_add(self):\n", " self.assertEqual(add(1, 2), 3)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " unittest.main(argv=[''], verbosity=2, exit=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Testing QSCU" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "ExecuteTime": { "end_time": "2020-01-29T00:17:03.355147Z", "start_time": "2020-01-29T00:17:03.322372Z" }, "code_folding": [] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "test_add (__main__.TestAdd) ... ok\n", "test_most_sold (__main__.TestQSCU)\n", "Test if the get_most_sold functions returns the most sold item ... ok\n", "test_no_sold_items (__main__.TestQSCU)\n", "Test if the quantity of items is set to zero before any item is sold ... ok\n", "test_sell_item (__main__.TestQSCU)\n", "Test if the sell item function correctly updates the database ... ok\n", "\n", "----------------------------------------------------------------------\n", "Ran 4 tests in 0.011s\n", "\n", "OK\n" ] } ], "source": [ "# import unittest\n", "# from qscu import QSCU\n", "\n", "\n", "class TestQSCU(unittest.TestCase):\n", " def setup_test(self):\n", " \"\"\"Instantiate a databse in memory for the test.\"\"\"\n", " self.shop = QSCU(\":memory:\")\n", " self.shop.setup_db()\n", "\n", " def test_no_sold_items(self):\n", " \"\"\"Test if the quantity of items is set to zero before any item is sold\"\"\"\n", " self.setup_test()\n", "\n", " rows = self.shop.cursor.execute(\n", " \"\"\"\n", " SELECT name, sold\n", " FROM sales\n", " \"\"\"\n", " )\n", "\n", " for name, sold in rows:\n", " self.assertEqual(sold, 0)\n", "\n", " def test_sell_item(self):\n", " \"\"\"Test if the sell item function correctly updates the database\"\"\"\n", " self.setup_test()\n", "\n", " expected_result = {1: 4, 2: 5}\n", "\n", " self.shop.sell_item(1, 1)\n", " self.shop.sell_item(2, 2)\n", " self.shop.sell_item(1, 3)\n", " self.shop.sell_item(2, 3)\n", "\n", " rows = self.shop.cursor.execute(\n", " \"\"\"\n", " SELECT product_id, sold\n", " FROM sales\n", " \"\"\"\n", " )\n", "\n", " for product_id, sold in rows:\n", " if product_id in expected_result:\n", " self.assertEqual(sold, expected_result[product_id])\n", " else:\n", " self.assertEqual(sold, 0)\n", "\n", " def test_most_sold(self):\n", " \"\"\"Test if the get_most_sold functions returns the most sold item\"\"\"\n", " self.setup_test()\n", "\n", " # Case when no item has been sold: it's ok if we return any, but it must tell sold 0 times\n", " self.assertEqual(self.shop.get_most_sold()[1], 0)\n", "\n", " # Another case: every item has been sold one time\n", " self.shop.sell_item(1, 3)\n", " self.shop.sell_item(2, 5)\n", " self.shop.sell_item(3, 2)\n", "\n", " self.assertEqual(self.shop.get_most_sold(), (\"Macchiato\", 5))\n", "\n", " # More elaborate case: does our function work when update values again?\n", " self.shop.sell_item(1, 5)\n", " self.shop.sell_item(2, 2)\n", " self.assertEqual(self.shop.get_most_sold(), (\"Espresso\", 8))\n", "\n", "\n", "if __name__ == \"__main__\":\n", " unittest.main(argv=[''], verbosity=2, exit=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "That's all!\n", "Thank you for coming!\n", "\n", "You can find the slides at: tiny.cc/intro_python\n", "\n", "Please come to us if you have any questions :)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.3" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": true } }, "nbformat": 4, "nbformat_minor": 2 }