{ "cells": [ { "cell_type": "markdown", "metadata": { "toc": true }, "source": [ "

Table of Contents

\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Variables\n", "\n", "Use `=` to **assign** a value to a variable." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = 5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are two options for displaying the value of `x`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Or use the `print` function:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A cell can contain multiple lines of code:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "length = 10\n", "width = 2.5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Text prefaced with `#` is a **comment**, which is a note to people reading the code and is ignored by Python." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Calculate area of rectangle\n", "area = length * width\n", "\n", "# Display the area\n", "area" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What if we change the value of a variable?\n", "- Currently, `length` is 10 and `width` is 2.5" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "width = 3.5" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "area" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "length * width" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we go up to the previous cell that calculated the rectangle area, what is the output?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- The calculated area corresponds to the *new* value of `width` (3.5) even though the cell immediately above shows `width` being assigned a value of 2.5\n", "- Jupyter notebooks are nonlinear—a collection of cells that can be run out of order\n", " - Need to be cautious when running cells out of order!\n", " - It's good practice to periodically restart the kernel and run all cells in order" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Naming Variables\n", "\n", "- Can only use letters, numbers and underscore `_`\n", "- Can't start with a number\n", " - `day1` is ok, but `1day` will cause an error\n", "- Use descriptive names and separate words with an underscore (e.g. `first_name`, `land_area`)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "avogadro = 6.02e23" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Try typing `av` and then press `Tab` and see what happens" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "lines_to_next_cell": 2 }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Auto-complete! One of the very handy features of IPython." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Data Types\n", "\n", "So far we've worked two types of numbers in Python:\n", "- `int` (integer)\n", "- `float` (decimal numbers)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "n = 42\n", "pi = 3.14159" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The type of a variable is determined by the value assigned to it\n", "- We can use the function `type` to find out the type" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type(pi)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type(n)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Strings\n", "\n", "- Text data is of the type `str`, which stands for **string**: a sequence of characters enclosed in single or double quotation marks\n", "- The characters in a string can be letters, numbers, punctuation, symbols, etc." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "today = \"Tuesday\"\n", "tomorrow = \"Wednesday\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type(today)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Strings can be **concatenated** with the `+` operator:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "statement = \"Today is \" + today\n", "statement" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "lines_to_next_cell": 2 }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Comparison & Logic\n", "\n", "We can also use comparison and logic operators (`<`, `>`, `==`, `!=`, `<=`, `>=`, `and`, `or`, `not`), which will return either `True` or `False`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "year = 2018\n", "year" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "year > 2000" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "year == 1990" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note the double equals sign above\n", "- Single equals sign `=` is for assigning a value to a variable\n", "- Double equals sign `==` is for *checking* if values are equal to each other" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`not` reverses the outcome from a comparison." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "not year == 1990" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`and` checks if both comparisons are `True`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "3 < 4 and 5 > 10" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`or` checks if *at least* one of the comparisons are `True`.\n", "- Below we're also taking the output of the comparison and assigning it to a variable `result`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "result = 3 < 4 or 5 > 10\n", "result" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The resulting `True` or `False` value is of type `bool`, short for **Boolean**." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type(result)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As we'll see later, Boolean comparisons like these are important when extracting specific values from a larger set of values." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Conditionals\n", "\n", "Another common use of Boolean comparison is with a conditional statement, where the code after the comparison only is executed if the comparison is `True`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = 12\n", "\n", "if a < 10:\n", " print(\"a is less than 10\")\n", "else:\n", " print(\"a is greater than or equal to 10\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- Note the **indented** line after each colon `:`\n", "- Indentation is very important in Python!\n", "- In this example, indentation indicates which code is executed if the conditional statement is `True` and which code is executed if the conditional is not `True`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Data Types - Recap\n", "\n", "- Integer (`int` — whole numbers)\n", "- Float (`float` — numbers containing decimals)\n", "- String (`str` — words, sentences, other text)\n", "- Boolean (`bool` — `True` or `False`)\n", "- and many others!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Exercise 1.1\n", "\n", "**a)** Create a variable `y` with a value of `7`\n", "\n", "The cell below is your first look at an autograded Jupyter notebook cell. The ideas is that, until you replace the contents of that cell with your answer python will raise an error called \"NotImplemented\". Go ahead and remove replace that statement with your own answer." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "lines_to_next_cell": 2, "nbgrader": { "checksum": "8c8fc363b8817c3e277e7070f77238ea", "grade": false, "grade_id": "cell-4835970fca5f66f9", "locked": false, "schema_version": 1, "solution": true } }, "outputs": [], "source": [ "# YOUR CODE HERE\n", "raise NotImplementedError()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You statement should pass the following test:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "lines_to_next_cell": 2, "nbgrader": { "checksum": "8ba1d78dad970b97cdfee8bacb09f270", "grade": true, "grade_id": "cell-9362f71eb05dffad", "locked": true, "points": 2, "schema_version": 1, "solution": false } }, "outputs": [], "source": [ "from numpy.testing import assert_almost_equal\n", "\n", "assert_almost_equal(y, 7, decimal=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**b)** Create a variable `two_y` with a value of `2 * y`" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "lines_to_next_cell": 2, "nbgrader": { "checksum": "c88a0b4b359bcbff4b440549d985d17b", "grade": true, "grade_id": "cell-ec6af3f7c1328375", "locked": false, "points": 2, "schema_version": 1, "solution": true } }, "outputs": [], "source": [ "# YOUR CODE HERE\n", "raise NotImplementedError()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**c)** Change the value of `y` to `9`. What is the value of `two_y` now, `14` or `18`?" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "lines_to_next_cell": 2, "nbgrader": { "checksum": "3a1108de203d53914adadecae637deb2", "grade": true, "grade_id": "cell-886acb4e6655300d", "locked": false, "points": 3, "schema_version": 1, "solution": true } }, "outputs": [], "source": [ "# YOUR CODE HERE\n", "raise NotImplementedError()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Bonus exercises" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**d) Concatenating strings and integers**\n", "\n", "Assign a value of `2018` to the variable `year`. What happens if you use the `+` operator to add the string `'The year is '` with the variable `year`, as shown below? (*You'll need to copy the code below into a cell in your notebook in order to run it.*)\n", "```python\n", "observation = 'The year is ' + year\n", "```\n", "> You'll find you get an error message because Python doesn't know how to add an integer and a string together.\n", "\n", "You can use *typecasting* to change the type of an object in Python. For example, you can convert the integer `2018` to the string `'2018'` using the function `str()`. Try running the code below in your notebook and then display the value of the variable `observation`:\n", "```python\n", "observation = 'The year is ' + str(year)\n", "```\n", "- Now create a variable `num_bottles` with a value of `99` (integer) and a variable `song_words` with a value of `' bottles of beer on the wall'`.\n", "- Use the `+` operator and the `str()` function to concatenate `num_bottles` with `song_words` and confirm that it produces the output `'99 bottles of beer on the wall'`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**e) Other mathematical operators**\n", "\n", "What are the results of the following operations?\n", "\n", "- `9 % 3`\n", "- `10 % 3`\n", "- `11 % 3`\n", "\n", "How about the above operations with the `%` operator replaced with the `//` operator (e.g. `9 // 3`)? Based on these results, what do you think the `%` and `//` operators do? [(Hint)](https://jakevdp.github.io/WhirlwindTourOfPython/04-semantics-operators.html)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**f) Conditional statements**\n", "\n", "Create a conditional statement that prints `'Leap year'` if the value of the variable `year` is divisible by 4, and `'Not a leap year'` otherwise. Test your conditional statement by assigning different values to `year` and re-running the code." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Functions\n", "\n", "- Functions are bundles of code that can be re-used\n", "- Python has many handy built-in functions, for example:\n", " - `print`\n", " - `type`\n", " - `round`\n", " - `abs`\n", " - `sum`\n", "- You can also define your own functions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Built-In Functions" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "round(3.14159)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Auto-complete works for functions too. Try typing `ro` followed by `Tab`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "lines_to_next_cell": 2 }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- Inputs to a function are called **arguments**\n", "- Arguments can be required or optional\n", "- Functions **return** an output value or a `None` output\n", " - `round(3.14159)` returns `3`\n", " - `print('hello')` returns `None`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Use `?` after the function name to see the documentation. (remove the # to try this)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# round?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- Python documentation is sometimes helpful and sometimes totally confusing, especially when you're first learning the language\n", "- Other online resources can be much more helpful and easier to understand, for example:\n", " - Tutorials\n", " - Blog posts with examples and code\n", " - Questions and answers posted on Stack Overflow and other forums\n", "- Think of Google search as an essential component in your Python workflow!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "round(3.14159, 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When we call a function, what do we do with its output?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1) We can simply display the output on the screen to see what it looks like:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "round(1 / 3, 5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "2) We can assign it to a variable so that we can use it elsewhere:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "one_third = round(1 / 3, 5)\n", "one_third" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Defining Functions\n", "\n", "- We can define functions anywhere in our code using the `def` keyword\n", "- The contents of the function are an **indented block**\n", "- Use the `return` keyword to return an output" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "lines_to_next_cell": 2 }, "outputs": [], "source": [ "def fraction(num, denom):\n", " result = num / denom\n", " return result" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can **call** our function by supplying input values in the same order they were defined above (numerator followed by denominator).\n", "\n", "- These inputs are referred to as **positional arguments**." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fraction(30, 7)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Or, we can use use the labels `num` and `denom` to specify input values in any order we want in our function call.\n", "- These inputs are referred to as **keyword arguments**.\n", "\n", "> Pro Tip: Auto-complete works for keyword arguments too!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fraction(denom=7, num=30)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Some terminology:\n", "\n", "- When we *define* a function, the inputs defined inside parentheses are called **parameters**\n", "- When we *call* a function, the input *values* we pass to the function are called **arguments**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also specify **default values** for inputs\n", "- When *defining* the function, these default input values must be listed *after* any inputs that don't have default values" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "lines_to_next_cell": 2 }, "outputs": [], "source": [ "def fraction_rounded(num, denom, ndigits=2):\n", " result = round(num / denom, ndigits)\n", " return result" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fraction_rounded(denom=7, num=30)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fraction_rounded(denom=7, num=30, ndigits=6)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- It is helpful to include a description of the function.\n", "- There is a special syntax for this in Python that makes sure that the message shows up in the help message." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "lines_to_next_cell": 2 }, "outputs": [], "source": [ "def fraction_rounded(num, denom, ndigits=2):\n", " \"\"\"Return the fraction num/denom rounded to ndigits\"\"\"\n", " result = round(num / denom, ndigits)\n", " return result" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The string between the `\"\"\"` is called the docstring and is shown in the help message, so it is important to write a clear description of the function here." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As with built-in functions, `?` can be used to get help for user defined functions." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# fraction_rounded?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The entire source code of a function can be displayed with `??` (if it is short enough)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# fraction_rounded??" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Related functions can be bundled together in libraries (modules/packages)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Exercise 1.2\n", "\n", "**a)** Write a function which takes an input of temperature in degrees Celsius, and returns an output of temperature in degrees Fahrenheit (multiply the temperature in degrees C by 1.8 and add 32)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "checksum": "ee6c5d820c0f971fbb62517cc5a4f5eb", "grade": true, "grade_id": "cell-ef51470651518f36", "locked": false, "points": 2, "schema_version": 1, "solution": true } }, "outputs": [], "source": [ "# YOUR CODE HERE\n", "raise NotImplementedError()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "b) Use this function to convert 15 C to Fahrenheit, and assign the output to a variable temp_F" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "nbgrader": { "checksum": "6d0de1b7be4203dc903d5a2fc9b4c766", "grade": false, "grade_id": "cell-ec6800b6465d8a7b", "locked": false, "schema_version": 1, "solution": true } }, "outputs": [], "source": [ "# YOUR CODE HERE\n", "raise NotImplementedError()\n", "\n", "# You code sould pass the following test:\n", "from numpy.testing import assert_almost_equal\n", "\n", "assert_almost_equal(temp_F, 59.0, decimal=1)\n", "print(convert_celsius(30))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "deletable": false, "editable": false, "nbgrader": { "checksum": "23b5eba537eb3db8f3db1f83a8f30dac", "grade": true, "grade_id": "cell-7aeb0c61250c5a72", "locked": true, "points": 2, "schema_version": 1, "solution": false } }, "outputs": [], "source": [ "# This cell contains a hiddent test that calls your function with another value for temp_celsius\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Bonus exercises\n", "\n", "**c)** Create a new function based on your function from part (a), which converts the temperature from Celsius to Fahrenheit and also prints a message about the temperature:\n", "- If the input temperature is less than 10 C, it prints `'Chilly!'`,\n", "- Otherwise, it prints `'OK'`.\n", "\n", "Call the function with different input temperatures to test it." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**d)** Modify your function from part (c) so that it accepts a second input called `temp_chilly`, which is used for the \"chilly\" temperature threshold (instead of always using 10 C). Test the function by calling it with various values for each of the two inputs." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Methods\n", "\n", "A **method** is a function that is \"attached\" to a Python object\n", "- e.g. String methods: `upper`, `lower`, `capitalize`, `replace`, `strip`, and many more\n", "- We use **dot notation** to access an object's methods\n", "\n", "> Note: Methods are a feature of *object oriented programming*, which we won't delve into here, but for more details, check out [this tutorial](https://www.datacamp.com/community/tutorials/python-oop-tutorial)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "message = \"Hello world.\"\n", "message.upper()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Did our variable `message` change?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "message" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Auto-complete works on methods too\n", "- Try typing `message.` (including the dot at the end) and then press `Tab` and see what happens" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "lines_to_next_cell": 2 }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "new_message = message.replace(\"world\", \"universe\")\n", "new_message" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Is the `replace` method case sensitive?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "message.replace(\"hello\", \"hi\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Methods can be **chained** together:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "shouting = message.upper().replace(\".\", \"!!!\")\n", "shouting" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Lists\n", "\n", "**Lists** are a common data structure to hold an ordered sequence of elements." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "planets = [\"Mercury\", \"Venus\", \"Earth\", \"Mars\", \"Jupiter\"]\n", "planets" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "prime_numbers = [2, 3, 5, 7, 11, 13]\n", "prime_numbers" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "different_data_types = [3.14, \"Canada\", 62 / 7, 1729]\n", "different_data_types" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lists can be added together with the `+` operator:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "planets + prime_numbers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can use the function `len` to get the length of a list" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "len(planets)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Each element in a list can be accessed by an **index**.\n", "- Note that Python indexes start with 0 instead of 1." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](img/list_index.png)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "planets[0]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "planets[3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "How can we access the element `'Earth'` from the list `planets`?" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "lines_to_next_cell": 2 }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "How can we access the last element in the list `planets`?" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "lines_to_next_cell": 2 }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What happens if we try to access `planets[10]`?" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "lines_to_next_cell": 2 }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that for indexing we use square brackets `[]` whereas for function calls we use parentheses `()`. This is one of the (many) features that makes Python code easy to read.\n", "\n", "```python\n", "thing1 = something(5)\n", "thing2 = something_else[5]\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Without having any other information about the code above, we already know that `something` is a *function*, whereas `something_else` is a *data structure* (such as a list).\n", "> Of course, it's good practice to give your functions and variables descriptive names, unlike the cryptic code above!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Slices\n", "\n", "Multiple elements in a list can be selected via **slicing**." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![](img/list_index.png)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "planets[1:3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Slicing is inclusive of the start of the range and exclusive of the end, so the slice `planets[1:3]` includes all elements from index 1 up to—but not including—index 3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Either the start or the end number of the range can be excluded to include all items to the beginning or end of the list, respectively." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "planets[:2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Modifying a List\n", "\n", "- Lists are modified \"in place\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "planets[3] = \"MARS!\"\n", "planets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can use methods such as `append` and `remove` to add or remove items from a list\n", "\n", "- As with string methods, list methods use dot notation" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "planets.append(\"Uranus\")\n", "planets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Loops\n", "\n", "A loop can be used to access the elements in a list or other Python data structure one at a time." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for planet in planets:\n", " print(planet)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The variable `planet` is re-created for every iteration in the loop until the list `planets` has been exhausted." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Operations can be performed on elements inside loops:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for planet in planets:\n", " print(\"I live on \" + planet)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Exercise 1.3\n", "\n", "**a)** Create a list called `numbers` containing the values: `7, -4, 1e8, 8.3, 287, 29, -2.5, 9.8`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**b)** Display a slice of `numbers` containing the last 3 items" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**c)** Loop over the items in `numbers` to print out each item multiplied by 10" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Bonus exercises\n", "\n", "**d) Creating a sequence of integers**\n", "\n", "The built-in function `range` produces a sequence of integers from a specified start (inclusive) to stop (exclusive). This can be helpful when we want to loop over a long sequence of numbers without manually creating a list of those numbers. Try copying the code below into your notebook and running it to see how it works:\n", "\n", "```python\n", "for num in range(7, 16):\n", " print(num)\n", "```\n", "\n", "Using the code above as a guide, and also using the techniques from previous bonus exercise 1.1(d) for concatenating an integer variable with a string:\n", "- Create a `for` loop that loops over a sequence of years from 1938 up to and including 2012, and for each year in the sequence, prints `'The year is '` plus the current value of the year.\n", "\n", "> In a later bonus exercise, we'll use this loop for downloading Environment Canada weather data!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**e) Negative indices**\n", "\n", "- Display the item at index `-1` of your list `numbers` from part (a).\n", "- How about index `-2`, `-3`, etc?\n", "- What do you conclude about negative indices?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**f) More about slices**\n", "\n", "- Display the slices `numbers[::2]`, `numbers[1:6:2]`, and `numbers[::-1]`.\n", "- What do you conclude about the number after the second colon?\n", "- How would you slice `numbers` to display every 3rd item starting from index 1?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**g) Indexing with strings**\n", "\n", "Create a variable `city` with a value of `'Vancouver'`.\n", "- Display the values of `city[0]` and `city[3:7]`.\n", "- What do you conclude about indexing string variables?\n", "- What happens if you try to assign `city[6] = 'Q'`?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Dictionaries\n", "\n", "A **dictionary** is a data structure that holds pairs of objects - keys and values." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fruit_colors = {\"banana\": \"yellow\", \"strawberry\": \"red\"}\n", "fruit_colors" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- Dictionaries work a lot like lists - except that they are indexed with **keys**.\n", "- Think about a key as a unique identifier for a set of values in the dictionary.\n", "- Keys can only have particular types - they have to be \"hashable\".\n", " - Strings and numeric types are acceptable, but lists aren't." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fruit_colors[\"banana\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To add an item to the dictionary, a value is assigned to a new dictionary key." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fruit_colors[\"apple\"] = \"green\"\n", "fruit_colors" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using loops with dictionaries iterates over the keys by default." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for fruit in fruit_colors:\n", " print(fruit + \" is \" + fruit_colors[fruit])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Trying to use a non-existing key, e.g. from a typo, throws an error message." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fruit_colors[\"bannana\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is an error message, commonly referred to as a \"traceback\". This message pinpoints what line in the code cell resulted in an error when it was executed, by pointing at it with an arrow (`---->`). This is helpful in figuring out what went wrong, especially when many lines of code are executed simultaneously." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Exercise 1.4\n", "\n", "a) In the `fruit_colors` dictionary:\n", "- Change the color of `apple` to `'red'`\n", "- Add an item with key `'plum'` and value of `'purple'`\n", "- Display the updated `fruit_colors` dictionary" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "b) Loop through the `fruit_colors` dictionary and print the fruit name (key) only if its color (value) is `'red'`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Bonus exercises\n", "\n", "c) Create a new *empty* dictionary `groceries` with the syntax `groceries = {}` and then display `groceries`. Add a key `'eggs'` with a value of `12` and display the updated `groceries` dictionary." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "d) Create a new dictionary `squares` whose keys are the integers `1`, `2`, `3`, `4`, `5`, and the value for each key is the key squared (so for key `1`, the value is `1`; for key `2`, the value is `4`; etc.).\n", "- Hint: See if you can find a couple of different ways to accomplish this task. One approach might involve a list along with an empty dictionary and a `for` loop." ] } ], "metadata": { "jupytext": { "cell_metadata_filter": "all", "formats": "ipynb", "notebook_metadata_filter": "all", "text_representation": { "extension": ".py", "format_name": "percent", "format_version": "1.2", "jupytext_version": "0.8.6" } }, "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.6.7" }, "livereveal": { "scroll": true, "theme": "solarized", "transition": "none" }, "nbsphinx": { "execute": "never" }, "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": true, "toc_position": { "height": "calc(100% - 180px)", "left": "10px", "top": "150px", "width": "267.797px" }, "toc_section_display": true, "toc_window_display": true } }, "nbformat": 4, "nbformat_minor": 2 }