{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Notebook-3: The Basics" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this first _proper_ programming lesson we are going to use the Python interpreter to perform simple operations, like numeric calculations that you would normally do on a calculator and slightly more advanced operations on words. The interpreter is what reads your code and converts that into the binary instructions that the computer can understand – think of it as translator between you and the low-level components (operating system, file system, network, display, etc.) of your machine. In these notebooks the interpreter is in the background and runs when you click the 'Run' button in a code cell (in future we'll see how we can use the Python interpreter with scripts of many lines of code). \n", "\n", "As we progress through the excercises we'll encounter a range of new programming concepts. At this stage don't worry too much about memorizing all of them; it is through repeated used and practice that they will eventually come naturally. Instead, here we want you to try to develop a _sense_ of what is going on and keep the concepts in mind when reading the examples... but the really important thing is to try to apply them while _doing the excercises_." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To help you get started, we have prepared an introductory video to aid your learning about the basic concepts in Python. Please note that by the time you have finished watching this video, you might need to re-launch binder. So if you have modified any part of your notebook, make sure to download the current version to your browser (the introductory video talks about how to do this).\n", "\n", "[![Notebook 3](http://img.youtube.com/vi/UDNtW3sy-og/0.jpg)](https://youtu.be/UDNtW3sy-og)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### How the exercises work\n", "\n", "Lastly, a few words on the excercises; in every notebook we've tried to develop a mix of exercises and examples to show you how Python works. There are four 'levels' of exercise:\n", "\n", "1. **Code from Scratch**: using examples already encountered in the lesson as a starting point, you will write some _very simple_ code (1-3 lines at most) into a blank code cell. \n", "2. **Supported Code**: using examples and exercises already encountered in the notebook, you will fill in somes 'gaps' in the lines of code where we've replaced some critical bits with (*???*) in order to make it work successfully.\n", "3. **Broken Code**: here we have deliberately broken something (sometimes, more than one thing) in the code and you will need to fix these before it will run successfully. Being able to _debug_ code is an integral part of being a programmer, and this will also require you to have an eye for detail because tiny typos and simple sloppiness are enough to break a computer program.\n", "4. **Applied Geo-Example**: this will be a much more advanced bit of code that will (we hope) run successfully right from the start. The point of these examples is to demonstrate a real-world _application_ of a concept covered in the lesson and we are asking you to spend some time puzzling over the code and adding comments about what you think is going on. Being able to read someone else's code and to make sense of what is going on is another crucial skill for a programmer. \n", "\n", "We're not expecting you to master the fourth level at this stage; in fact, some of the examples might be challenging even after a full year of classes. However, we think it's important to try to show you where we're trying to go as well as the steps involved in how we get there. It's like trying to follow directions from someone who only tells you 'turn left', 'turn right', 'go straight' – it's a lot easier to fill in the gaps and to understand what's going on if they say \"We're headed to London\" first!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Simple Operations\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Numeric Operations\n", "\n", "You already saw a really simple example of calculating the mean in Notebook 1, but let's recall that you can easily use Python to like a calculator. Run the code already present in the code cells and make sure you understand the output. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Basic Arithmetic\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### **Addition** and **Subtraction**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "3 - 2 + 10" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### **Multiplication** and **Division**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "2 * 5" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "10 / 5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### A challenge for you!\n", "Do you think the results of these two operations will be identical? If not, why? **Decide what you think the answer is _before_ running the code!**" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden", "solution2_first": true }, "outputs": [], "source": [ "print(4 * (2 - 8) + 2)\n", "print(4 * 2 - 8 + 2)" ] }, { "cell_type": "markdown", "metadata": { "solution2": "hidden" }, "source": [ "The results are different due to the order in which Python runs the operations. Anyway, remember the importance of **parentheses** in determining 'precedence' – which operations get done first." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You'll see that the code above encompases each formula in `print()` command on each line; this simply allows us to print out the results of both calculations when the code runs. We'll come back to this later." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "(3 * 2) - 10" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "is not the same as:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "3 * (2 - 10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exponents \n", "\n", "#### Powers\n", "\n", "If you use two asterisks instead of one then you'll be performing an **exponentiation**:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "2 ** 4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "That's the same as: " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "2 * 2 * 2 * 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So `2**4` is how we get 2-to-the-power-of-4 (the same as multiplying 2 together 4 times). Hopefully this all kind of rings a bell even if you've not studied any maths in a while.\n", "\n", "#### Roots\n", "\n", "So `2**4` is 2-to-the-power-of-4, but how do we get the square root (or fourth root) of a number? Right now, with what we've taught you so far, the best way is to remember that a square root is the same as an exponent of one-half. The fourth root is an exponent of one-quarter. Etc." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(2**8) # 2-to-the-8\n", "print(256**(1.0/8.0)) # 256-to-the-one-eighth" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Floating Point numbers\n", "\n", "Warning: the following two equations are not _always_ the same!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(1/8)\n", "print(1.0/8.0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Many programming languages (Python _used_ to be one of them) treat whole numbers (1, 8) differently from floating point numbers (1.0, 8.000000000001). In those cases, we get the answer `0` to the first equation because when we use whole numbers in our calculations we got whole numbers back. So `1/8` is obviously not `0`, but that's the nearest whole number to `0.125`! This is what we mean about computers doing _exactly_ what you tell them: sometimes you want 1/8 to equal 0, other times 0.125, and the computer doesn't know which answer you need unless you are very clear about what you want!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Modulo\n", "\n", "While we're on the topic of division, how do you get the 'remainder' of 9/2 – the bit _left over_ from the division? To get this there is a different symbol called the *modulo operator* which is a marked by a `%` sign. According in fact to the [Python Documentation](https://docs.python.org/2.7/reference/expressions.html)\n", "\n", ">The % (modulo) operator yields the remainder from the division of the first argument by the second.\n", "\n", "Using the modulo operator will thus return the remainder:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(9/2)\n", "print(9%2) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Just to make this clear: 2 goes into 9 exactly 4 times and then you have 1 left over. So: `(4 * 2) + 1 = 9`.\n", "\n", "For division which yields no remainder the operation will return a value of 0." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "8%2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### A challenge for you!\n", "\n", "What do you think will be the result of this operation? Work out your answer **before** running the code. " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "shown", "solution2_first": true }, "outputs": [], "source": [ "print( (2*3) ** 2 )" ] }, { "cell_type": "markdown", "metadata": { "solution2": "shown" }, "source": [ "The answer is 36 as Python would do the multiplication inside the parenthesis first." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now what do you think this will give you? Again, work out your answer **before** running the code. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print( (2*3) ** 2 / (12 % 5) )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the code below replace the question marks `???` with the appropriate code to produce a remainder of 6. You may need a calculator to help you. Run the code to check your answer (you can change your answer and run the code multiple times to get the right answer)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "(2+4) ** 2 % (120 / ???)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Operator Precedence\n", "\n", "The _operators_ +, -, \\*, \\*\\*, /, %, etc., and the parentheses are all evaluated (i.e. calculated) according to a set of rules that establish _precedence_, which is just a fancy way of saying: which calculations do we do first? There's a full list [here](http://www.mathcs.emory.edu/~valerie/courses/fall10/155/resources/op_precedence.html) but since that also lists a lot of operators we've not yet encountered it's easiest to summarise this in a table as follows:\n", "\n", "\\begin{array}{cl} \\hline\n", "Operator & Description \\\\ \\hline\n", "(\\ldots) & Parentheses \\\\ \n", "** & Exponentiation \\\\ \n", "+x, -x & Positive, Negative \\\\ \n", "*, /, \\% & Multiplication, Division, Remainder \\\\ \n", "+, - & Addition, Subtraction \\\\ \\hline\n", "\\end{array}\n", "\n", "So parentheses trump everything else, then exponents (so `2**5.0/2` is not the same as `2**(5.0/2)`), then positive/negative, and then multiplication/division before we finally get to addition and subtraction.\n", "\n", "### Division by Zero\n", "\n", "Also pay attention when *dividing by zero*. Python won't be able to compute any value and will return an *error* (which is sometimes also called an *exception*):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "(30 + 2 ) / 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### A challenge for you!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Replace the questions marks `???` in the following exercise with the appropriate code to purposufully cause a `ZeroDivisionError` exception (again, feel free to use a calculator and you can run the code multiple times)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "(1345 - 20 ) / ((- 3) ** 2 - ???)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "_Note:_ the *error message* is Python's way of telling you what went wrong in the operation. We'll get to these in more detail in a later lesson, but you'll notice that Python _always_ tries to tell you what it thinks went wrong and this is the starting point for all _debugging_. When something goes wrong in a program this error is like the first clue that puts you on the trail of the wrongdoer: sometimes one clue will lead to another, and another, and another... sometimes one clue is all you need. \n", "\n", "But regardless, **if you ignore these clues and just put up your hand and say \"It doesn't work!\" then we're not going to be very impressed**. We expect you to be able to explain the problem to us before we will help you with it. More on this later." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### More about Ints and Floats\n", "\n", "So we've seen some examples above of maths with *integers* (i.e. \"whole\" numbers) and maths with *floats* (i.e. \"decimal\" numbers). Both can be positive and negative (e.g. `-1` or `-254.32672`). Programmers, being lazy, often call integers _ints_ because it's faster and requires less typing.\n", "\n", "Any operation involving a mix of *floats* and *integers* will always yeld a *float*. For example, compare the output for the code below, but note how the resulting data type varies with the operation." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(7 * 4)\n", "print(7 * 4.0)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(20 / 5)\n", "print(20.0 / 5)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(22 / 7)\n", "print(22.0 / 7)\n", "print( int(22.0/7) )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that last ticky bit: we'll get to what `int(...)` means later, but if you remember that programmers are lazy then you might realise that it must be short for _integer_." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(6 + 3)\n", "print(6.0 + 3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The reason for this is that Python is *implicitly* converting (sometimes called *casting*) the numbers between the two different *data types*. This conversion doesn't happen with more complex bits of Python code, but for simple numbers Python tries to be helpful and save you the time and effort.\n", "\n", "_Note:_ the integer-to-float conversion might seem a bit of a pedantic distinction, but imagine if you were programming a banking application: you would definitely pay attention to all those decimals!\n", "\n", "### Some final maths questions...\n", "\n", "Let's start with calculating the area of a triangle. Here's the equation for the area of a triangle: $$A = \\frac{l_{base} * l_{height}}{2}$$\n", "\n", "So lets work out for a triangle that has sides of length 10 and 20! If you type the maths correctly into the empty block below you should get the answer: 100" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now let's work out the length of the hypotenuse of a right-angle triangle with the same side lengths as above: $$l = \\sqrt{x^2 + y^2}$$\n", "\n", "You might remember this as the Pythagorean Theorem. Type and run your code in the next cell - you should get an answer of about 22.4." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's move on to two _last_ harder ones. Write a line of code to [work out the area of a circle](https://www.khanacademy.org/math/basic-geo/basic-geo-area-perimeter/basic-geo-area-circumference/v/area-of-a-circle) of radius 6. Here's the formula: $$A = \\pi r^2$$ and you should get something around 113.1 as the area. Use 3.1412 for the constant pi." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now work out the _approximate_ [radius of a sphere](https://www.khanacademy.org/math/basic-geo/basic-geo-volume-surface-area/basic-geo-volumes/v/volume-of-a-sphere) whose volume is 85. To do this, you'll need to work backwards from the formula to calculate a volume... this might seem a little rough at first, but remembering how to rearrange a formula is really helpful for computational thinking!\n", "\n", "So what do you have to do to this formula: \n", "$$V = \\frac{4}{3} \\pi r^3$$\n", "\n", "Here's a hint to get you started:\n", "$$ r^3 = \\frac{3}{4 \\pi} V $$\n", "\n", "_Also:_ remember that you're going to need to work with decimal numbers, not whole numbers and write your code accordingly! You should get a final answer of about 2.7." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "_Note:_ there are a lot of different ways that you could write this formula as _code_ and still get the right answer. Getting the right answer is 50% of the job. The remaining 50% is about doing it in a way that is elegant and easy to read... as get further into the term we'll point out how elegance and legibility (also: commenting) matter." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## String Operations\n", "\n", "OK, so that's the basics of numbers. What about text?\n", "\n", "### How long is a piece of string?\n", "\n", "In most programming languages, text and words are called `string`s, which is really a fancy word to say a *sequence of characters* enclosed in single- or double-quotes (' or \"). This is a `string`:\n", "\n", "```{python}\n", "\"235opu$nlkgfd8 wp8ty fgdoy8p waklj ag9up0\"\n", "```\n", "\n", "So is this (from Shakespeare's _Twelfth Night_): \n", "```{python}\n", "\"If music be the food of love, play on; Give me excess of it, that, surfeiting, The appetite may sicken, and so die.\" \n", "```\n", "\n", "This might seem like stating the obvious but, computers can't automatically distinguish between Shakespeare and the work of a monkey hitting keys at random. As long as the characters are marked out by single- or double-quotes then as far as the computer is concerned the two sequences of characters above are `strings`. \n", "\n", "So even to ask the computer how many words there in the first 3 lines of _Twelfth Night_ means we have to 'teach' the computer what a word is by giving it rules to recognise the start or end of one, and even how to recognise the start and end of a line so that it can find the first three of them!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"I'm a string of text!\")\n", "print('Me too! *&($£(£_@~{}|?<>$)')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "_Note:_ As before, we'll be using the `print()` command on many lines of code; that is just a way to tell the Python interpreter to output somthing for us to see.\n", "\n", "### Single- or Double-Quotes?\n", "\n", "Although you can technically use either type of quote (`'` or `\"`), it is generally better to use double-quotes as a way to prevent errors if a single-quote is contained in your string:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"I'm contained within double quotes. I'll be fine.\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print('I'm sourrounded by single-quotes and I contain a single-quote so there may be trouble ahead...')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice the helpful error message after running the code above? We'll come back to how to read errors like these in more detail in the next notebook, but again Python is giving us hints about where we might have made a mistake." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Escape Club\n", "\n", "What do you do if your string contains double-quotes _and_ single-quotes? That's where the 'backslash' (`\\`, a kind of 'reverse division' symbol) comes in handy. The backslash is how we 'escape' characters so that we can do 'special' things with them when they should _normally_ do something else.\n", "\n", "In the example below, the backslash in front of the apostrophe in \"I'm\" says \"Don't treat this as 'normal' single-quote that means the end of the string, treat it as a literal single-quote in the middle of a longer string marked out by single-quotes." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print('I\\'m using the backslash.')\n", "print('I\\'m also using the backslash \\'\\\\\\' to escape the error normally caused by having single-quotes.')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's look at this a little more closely:\n", "* The first line is easy: the backslash in front of the single-quote in \"I'm\" allows us to use single-quotes to mark the start and end of the string. This is a silly example since we could also have written `\"I'm using the backslash\"` but you get the point.\n", "* The second line gets a little more complicated: you'll see that we've now escaped _three_ single-quotes (there are three occurences of `\"\\'\"`). But what's happening with `\"\\\\\"`? Well, we need an extra backslash in front of the backslash so that the computer knows to print a literal backslash (we are 'escaping' the normal function of a backslash to escape the character immediately after it) instead of reading it as escaping the one in front of the single-quote.\n", "\n", "That's pretty weird, but just to show you what's happening here it is without that extra backslash:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print('I\\'m also using the backslash \\'\\\\' to escape the error normally caused by having single-quotes.')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you run the code above, you'll see another error! Also notice that in the two lines of code, in the first the whole line is in one colour (meaning the computer can see that it's all _one_ string), but in the broken example right before this the text changes colour once we get to \"to escape the error...\" (meaning that the computer doesn't see it all as one string).\n", "\n", "The escape symbol crops up in a lot of other circumstances. For example, what if we wanted to tell Python that a string contains a newline (i.e. that the string is split across one or more lines, like our Shakespeare quote above should be)? \n", "\n", "Remember that programmers are always lazy when given half a chance and so they figured out that the easiest way to mark a newline was `\\n`. They used 'n' because it is fairly easy to remember that that means '*n*ewline', and the backslash 'escapes' us from the simple world where an 'n' is the letter 'n' into the computer's world where '`n`' is 'n', but `\\n` is a newline:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"If music be the food of love, play on;\\n Give me excess of it, that, surfeiting ,\\n The appetite may sicken, and so die.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "See how that wraps the text on the `\\n`? Also note that the computer is printing _exactly_ what we told it to do: I kept a space between the `\\n` and the start of the next line. If you squint, then you can see that lines 2 and 3 are indented by the width of one space character. There's also an extra space after 'surfeiting' before the comma.\n", "\n", "#### Why details matters\n", "\n", "We say this a lot later too, but you might as well start learning this fact now: spaces in a string _matter_. To a computer `\" A string\"` and `\"A string\"` are _not_ the same. Notice that there is a single space in front of the 'A'. As a human being we tend to just skip over that space (especially if it's hard to see), but to a computer one string starts with 'A' and the other with ' ', so they are _completely different_.\n", "\n", "Further, numbers and strings are _not_ the interachangeable: `\"2016\"` is _not_ the same as `2016`. The first is a string that happens to contain the characters 2, 0, 1, and 6. The second is an integer number one larger than 2015." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"2016\")\n", "print(2016)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As you can see from running the code above, it's a bit annoying that they look the same when we print them. But if you run the next lines of code (_after_ thinking about what they might do), you'll see how Python tries to be helpful with its errors:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "2015 + 1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"2015\" + 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "See how the first line of code prints `2016`, but the second line of code (which tries to add together a string `\"2015\"` and the number `1`) gives you an error that lazily tells you about a problem with `str` (i.e. string) and `int` (i.e. integer) 'concatentation'. More on concatenation in a minute.\n", "\n", "#### Advanced laziness\n", "\n", "Obviously, having a _lot_ of `\\n` markers would be hard to read and a potential problem if you wanted to copy and paste the text into a different application. If you have a long block of text then you can avoid the whole issue by putting your text inside *triple-quotes*:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"\"\"Hi there,\n", "this time, \n", "I won't need those annoying newline characters.\n", "I also don't have problems with \"quotes\" or 'quotes'! \"\"\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Adding with strings (concatenation)\n", "\n", "As with *numbers*, there are many things that you can do with strings. The simplest, however, is like addition (which is why it uses a `+`): when you add strings together you get a new, longer string that contains the characters of the original strings. This is usually called **concatenation**:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"String1\" + \"String2\")\n", "print(\"Hey, looks like\" + \" I'm \" + \"adding \"+ \"6\" +\" strings\" + \" together\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So just like you would do to add two numbers together, we can add \"String1\" and \"String2\" together to get \"String1String2\". But notice that the `+` operator doesn't insert whitespace (i.e. a ' ' character) or anything else. It just sticks the two strings together _exactly_ as they are.\n", "\n", "And just like we can add together a whole set of numbers, we can add together a whole set of strings as in the second line beginning \"Hey, looks like...\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### A challenge for you!\n", "Replace the questions marks \"???\" in the following exercise with the appropriate code to make it work" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"This is code \" ??? \" camp's notebook is \" ??? \" number \" + \"2.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Multiplication\n", "\n", "If you use the *multiplication* operator (`*`) on a string then you will multiply the string by the value of the multiplier." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"I like Python a lot\" + \"!\" * 25)\n", "print(\"Foo \" * 5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### A challenge for you!\n", "What do you think will be the output of this code? (Work out your answer _before_ running the code)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "20 * '5'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, why do you think the next example below doesn't work? (_Read the error output if you're not sure what's going on._)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"5\" * \"2\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## What is a variable?\n", "---\n", "\n", "So far, everything we've done was about performing some kind of calculation on an integer, float, or string, and then showing the result. Given that a lot of programming doesn't involve solving everything in one easy line, how do you save an answer so that you can re-use it later? Let's start with the first true programming concept: the **variable**.\n", "\n", "If you have studied other programming languages before then the concept of the variable will be so familiar to you that it's hard to remember even having to learn it! Some people think of a [variable simply as \"a box\"](https://www.youtube.com/watch?v=V0aBwgLRNXI) that contains _values_ that we want to store and retrieve in the future. However, we think it might be more useful to think of a variable as the _label_ of a box in which we put something: for programmers, the label is how we remember what we put in the box and where we put it. \n", "\n", "Let me try to explain: if you [watched](https://www.youtube.com/watch?v=AkFi90lZmXA) the introductory [videos](https://www.youtube.com/watch?v=VBDoT8o4q00) in the previous notebook, then you'll remember that the computer stores 'information' in lots of places (in memory, on the hard drive, etc.), but it doesn't use an addressing system that you or I would be able to read. Instead, it will use a long, complicated number that tells the computer \"Go look in this place for what to do when the mouse is clicked\" or \"Go look what to do when someone asks you to add together 1 and 5\". In the same way that Python translates between what we humans can deal with and what the computer can deal with, it also translates between the 'labels' that we use to refer to different boxes storing different things and how the computer finds what we _actually_ put there.\n", "\n", "Here's an example:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "result = -2 * 10" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Hmmmm, nothing printed out this time... \n", "\n", "That's because this time we gave Python a bax with the label \"result\" in which to put the result of multiplying -2 and 10." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-20\n" ] } ], "source": [ "result = -2 * 10\n", "print(result)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Check it out! We _assigned_ the outcome of `-2 * 10` to a variable called `result`; then we printed out the value of the variable. \n", "\n", "[This video](http://img.youtube.com/vi/_sVtcPgHAjI/0.jpg) may help you to further understand the concept of a 'variable':\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Copying variables\n", "\n", "And variables can assigned to other variables using the `=` operator in the same way that the result of the maths operation above could be assigned to a new variable." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "myFirstVariable = 2 * 5\n", "print(myFirstVariable)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mySecondVariable = myFirstVariable\n", "print(mySecondVariable)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Cool, both variables have the same value! We _assigned_ the result of `2 * 5` to a variable named `myFirstVariable` and then we assigned this value to a _second_ variable called `mySecondVariable`. \n", "\n", "But why is this called assignment (or, in plain English, copying)? Well what happens when I change the first variable `myFirstVariable`? Will the second change as well? " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "myFirstVariable = 2\n", "print(myFirstVariable)\n", "print(mySecondVariable)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Whoa! `mySecondVariable` didn't change and still remembers what we _assigned_ to in the first time. \n", "Basically, we took the `myFirstVariable` label and attached it to a different box.\n", "\n", "As the [Python Programming Wikibook explains](https://en.wikibooks.org/wiki/Python_Programming/Data_Types), when you assign a variable you are just pointing this variable to an object (a value) which is stored somewhere in the memory." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python variables are a kind of 'label' (as the YouTube video above illustrates – watch it!). So when assigning new values to already *declared* variables (i.e. variables that already exist in your code) you are not overwriting the old values but simply \"moving\" the label from one value to another.\n", "\n", "That's why in Python variables have a `name`, a `data-type` and a `value`.\n", "\n", "| Name | Data Type | Value |\n", "|:---------------:|:---------:|:-----:|\n", "| myFirstVariable | integer | 1 |" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### A challenge for you!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the code cell below:\n", "a) define a variable called \"name\" and assign it a value of your choice, then \n", "b) print it with the \"print\" command\n", "\n", "For example:\n", "\n", "`name = \"Peter\"`\n", "\n", "`print(name)`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Replace the questions marks `???` in the following lines of code with the appropriate code to make it work (i.e. not produce an error)." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden", "solution2_first": true }, "outputs": [], "source": [ "cheers ??? name ??? \" is awesome!\"\n", "print(cheers)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden" }, "outputs": [], "source": [ "cheers = name + \" is awesome!\"\n", "print(cheers)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Naming variables\n", "\n", "How do you choose a variable name (i.e. label) in Python? \n", "\n", "Here's a short list of the conventions:\n", "* names may contain letters and/or numbers (e.g. `myVar2`)\n", "* names cannot begin with a number (e.g. `2myVar`)\n", "* names may contain an underscore (\"\\_\") (e.g. `my_var_2`)\n", "* names can be of any length (e.g. `m2` or `mySecondVariableIsReallyLong`)\n", "* you cannot use Python keywords (e.g. `print`)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So this block of code below will run:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "famous_geographer = \"Mercator\"\n", "print(famous_geographer)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But this block of code will not:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "1st_geographic_projection = \"\"\" Mercator's most famous Geographic Projection \n", "is a cylindrical map projection \n", "that retains the ability\n", "to ability to represent lines of constant course (loxodromes)\"\"\"\n", "\n", "print(1st_geographic_projection)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice how the notebook has coloured the text so that the '1' in what we wanted to make the variable name stands out? Again, that's Python trying to help us figure out what is going wrong, but it requires that you look closely at the output of the error message." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### A final warning\n", "\n", "Remember that we said the string `\" Some text\"` and the string `\"Some text\"` are different because the space at the start of the string changes everything? The same sort of _strict_ checking is true for variables: in short, Python is case-sensitive! \n", "\n", "This means that `this_var` and `This_var` are two different variables and can refer to two different boxes:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "this_var = \"Mercator\"\n", "This_var = \"Galileo\"\n", "\n", "print(this_var)\n", "print(This_var)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As for many issues related to Python's *style*, it is good practice to always refer to [the offical PEP 8 -- Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/#naming-conventions)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For more examples of Python variables check out also [OpenTechSchool's intro to Python](http://opentechschool.github.io/python-beginners/en/variables.html)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Code (general excercises)\n", "\n", "Now that we've had a taste of the fantastic Python programming world, let's solidify our newly acquired skills with a final round of excercises." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Code from scratch\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Exercise 1 \n", "\n", "Look at the following example (and its output):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "old_satellite = 'Sputnik 1'\n", "old_satellite_description = \" was the first artificial Earth satellite, launched from the Soviet Union on the 4th of October, 1957.\"\n", "print(\"Здравствуйте! My name is \" + old_satellite)\n", "print(old_satellite + old_satellite_description)" ] }, { "cell_type": "markdown", "metadata": { "solution2": "hidden", "solution2_first": true }, "source": [ "Similar to the example above, in the code cell below:\n", "1. define a variable named `new_satellite` with value `landsat`\n", "2. try to print its name\n", "3. then try to concatenate its name with another variable description of your choice, \n", "4. and print them." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden" }, "outputs": [], "source": [ "new_satellite = 'Landsat'\n", "print(new_satellite)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden" }, "outputs": [], "source": [ "print(\"The new satellite is \" + new_satellite + \" and the old satellite is \" + old_satellite)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Supported code\n", "\n", "Replace the questions marks `???` in the following exercise with the appropriate code to make it work" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Exercise 2\n", "\n", "Landsat is a bit generic, the correct name is Landsat 8. How would you put together these two different Data Types? Remember what we've seen about casting? Edit the code below to make it work. " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden", "solution2_first": true }, "outputs": [], "source": [ "print(\"Hello there \" + (new_satellite) + ??? )" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden" }, "outputs": [], "source": [ "print(\"Hello there \" + new_satellite + \" 8\" )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Excercise 3\n", "\n", "According to its Wikipedia page Sputnik 1 was a 58 cm diameter polished metal sphere. If a cm = 0.393700787 inches what was its diameter in inches? Edit the code below to make it work. " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden", "solution2_first": true }, "outputs": [], "source": [ "diameter_cm = 58\n", "cm2inches = 0.393700787\n", "diameter_inches = diameter_cm ??? cm2inches\n", "print(diameter_inches)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden" }, "outputs": [], "source": [ "diameter_cm = 58\n", "cm2inches = 0.393700787\n", "diameter_inches = diameter_cm * cm2inches\n", "print(diameter_inches)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Exercise 4\n", "\n", "Wat was its volume (in cubic cm)? # NOTE: the first line below we are \"importing\" the `math` module and assigning to a variable `PI` the value of pi (3.14...). Edit the code to make it work. " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden", "solution2_first": true }, "outputs": [], "source": [ "import math\n", "PI = math.pi\n", "\n", "radius_cm = diameter_cm/2\n", "volume = (4/3) ??? PI ??? (radius_cm ??? 3 )\n", "print(volume)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden" }, "outputs": [], "source": [ "import math\n", "PI = math.pi\n", "\n", "radius_cm = diameter_cm/2\n", "volume = (4/3) * PI * (radius_cm ** 3 )\n", "print(volume)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Broken code\n", "\n", "mmh..something's broken in the following line of code; can you spot the error(s)? Hint: remember what we said about different data types..." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden", "solution2_first": true }, "outputs": [], "source": [ "print(new_satellite + \"has a Near Infrared (NI), \\\n", "which band captures light in the wavelength from \"+\n", " 770 +\n", " \" to \" +\n", " 900 +\n", " \" nanometers.\" )" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden" }, "outputs": [], "source": [ "# The error message indicates a type error, as we can only concatenate string\n", "# The code should work by including \"\" to the numbers\n", "\n", "print(new_satellite + \" has a Near Infrared (NI), \\\n", "which band captures light in the wavelength from \"+\n", " \"770\" +\n", " \" to \" +\n", " \"900\" +\n", " \" nanometers.\" )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Code (Applied Geo-example)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this excercise you'll dip a toe in the wonderful world of web maps!\n", "\n", "We are going to create a *geographic marker* (a pin on the map!) on top of [OpenStreetMap (OSM)](https://wiki.openstreetmap.org/wiki/About_OpenStreetMap) to visualise King's College location.\n", "\n", "To do so we'll have to create a string representing a web `URL` (that's the [address you type in your browser](https://en.wikipedia.org/wiki/Uniform_Resource_Locator) when your surf the web) pointing to OSM website.\n", "\n", "Now, as you can see there are two variables containing King's College Longitute/Latitude coordinate position. You will need to use them within the variable `KCL_position`. Unfortunately they are in the wrong data type! Also, there might be something missing in the code.\n", "\n", "*HINT:* To convert (*cast*) a `float` to a `string` use the `str()` function (we haven't talked about functions yet, but see if you can work it out). You'll also need to think about how to concatenate strings? \n", "\n", "Replace the `???` in the code below to make it work." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden", "solution2_first": true }, "outputs": [], "source": [ "# King's College coordinates\n", "# What format are they in? Does it seem appropriate?\n", "longitude = -0.11596798896789551\n", "latitude = 51.51130657591914\n", "\n", "#cast the floats to strings\n", "??? = str(longitude)\n", "lat = str(???)\n", "\n", "# King's College marker\n", "KCL_position = \"https://www.openstreetmap.org/?mlat=\"+lat+\"8&mlon=\"+lon+\"#map=15/\"+lat+\"/\"+lon\n", " \n", "print(KCL_position)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "solution2": "hidden" }, "outputs": [], "source": [ "# King's College coordinates\n", "# What format are they in? Does it seem appropriate?\n", "longitude = -0.11596798896789551\n", "latitude = 51.51130657591914\n", "\n", "#cast the floats to strings\n", "lon = str(longitude)\n", "lat = str(latitude)\n", "\n", "# King's College marker\n", "KCL_position = \"https://www.openstreetmap.org/?mlat=\"+lat+\"8&mlon=\"+lon+\"#map=15/\"+lat+\"/\"+lon\n", " \n", "print(KCL_position)" ] }, { "cell_type": "markdown", "metadata": { "solution2": "hidden" }, "source": [ "Now click on the outputed string and behold! You'll be flying to King's." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Further references:\n", "\n", "For the most curious among you.\n", "\n", "On this lesson's topic:\n", "- [StackOverflow: In Python, why can a function modify some arguments as perceived by the caller, but not others?](http://stackoverflow.com/questions/575196/in-python-why-can-a-function-modify-some-arguments-as-perceived-by-the-caller)\n", "- [StackOverflow: Is it possible only to declare a variable without assigning any value in Python?](http://stackoverflow.com/questions/664294/is-it-possible-only-to-declare-a-variable-without-assigning-any-value-in-python)\n", "- [YouTube Video 1](https://www.youtube.com/watch?v=D48iCw3WWpI)\n", "- [YouTube Video 2 (*slightly* longer)](https://www.youtube.com/watch?v=rkx5_MRAV3A)\n", "\n", "General list or resources\n", "- [Awesome list of resources](https://github.com/vinta/awesome-python)\n", "- [Python Docs](https://docs.python.org/2.7/tutorial/introduction.html)\n", "- [HitchHiker's guide to Python](http://docs.python-guide.org/en/latest/intro/learning/)\n", "- [Python for Informatics](http://www.pythonlearn.com/book_007.pdf)\n", "- [Learn Python the Hard Way](http://learnpythonthehardway.org/book/)\n", "- [CodeAcademy](https://www.codecademy.com/learn/python)\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Credits!\n", "\n", "#### Contributors:\n", "The following individuals have contributed to these teaching materials: \n", "- [James Millington](https://github.com/jamesdamillington)\n", "- [Jon Reades](https://github.com/jreades)\n", "- [Michele Ferretti](https://github.com/miccferr)\n", "- [Zahratu Shabrina](https://github.com/zarashabrina)\n", "\n", "#### License\n", "The content and structure of this teaching project itself is licensed under the [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 license](https://creativecommons.org/licenses/by-nc-sa/4.0/), and the contributing source code is licensed under [The MIT License](https://opensource.org/licenses/mit-license.php).\n", "\n", "#### Acknowledgements:\n", "Supported by the [Royal Geographical Society](https://www.rgs.org/HomePage.htm) (with the Institute of British Geographers) with a Ray Y Gildea Jr Award.\n", "\n", "#### Potential Dependencies:\n", "This notebook may depend on the following libraries: None" ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.10.5" } }, "nbformat": 4, "nbformat_minor": 2 }