{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "A powerful calculator\n", "=====================\n", "\n", "Python prompt and Read-Eval-Print Loop (REPL)\n", "---------------------------------------------\n", "\n", "Python is an *interpreted* language. We can collect sequences of commands into text files and save this to file as a *Python program*. It is convention that these files have the file extension “`.py`”, for example `hello.py`.\n", "\n", "We can also enter individual commands at the Python prompt which are immediately evaluated and carried out by the Python interpreter. This is very useful for the programmer/learner to understand how to use certain commands (often before one puts these commands together in a longer Python program). Python’s role can be described as Reading the command, Evaluating it, Printing the evaluated value and repeating (Loop) the cycle – this is the origin of the REPL abbreviation.\n", "\n", "Python comes with a basic terminal prompt; you may see examples from this with `>>>` marking the input:\n", "\n", "\n", " >>> 2 + 2\n", " 4\n", "\n", "We are using a more powerful REPL interface, the Jupyter Notebook. Blocks of code appear with an `In` prompt next to them:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "9" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "4 + 5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To edit the code, click inside the code area. You should get a green border around it. To run it, press Shift-Enter." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Calculator\n", "----------\n", "\n", "Basic operations such as addition (`+`), subtraction (`-`), multiplication (`*`), division (`/`) and exponentiation (`**`) work (mostly) as expected:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "10010" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "10 + 10000" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "40.5" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "42 - 1.5" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "517" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "47 * 11" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "20.0" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "10 / 0.5" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2**2 # Exponentiation ('to the power of') is **, NOT ^" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "8" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2**3" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "16" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2**4" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2 + 2" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# This is a comment\n", "2 + 2" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2 + 2 # and a comment on the same line as code" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "and, using the fact that $\\sqrt[n]{x} = x^{1/n}$, we can compute the $\\sqrt{3} = 1.732050\\dots$ using `**`:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "1.7320508075688772" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "3**0.5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Parenthesis can be used for grouping:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "25" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2 * 10 + 5" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "30" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "2 * (10 + 5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Integer division\n", "----------------\n", "\n", "In Python 3, division works as you'd expect:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "2.5" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "15/6" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In Python 2, however, `15/6` will give you `2`.\n", "\n", "\n", "This phenomenon is known (in many programming languages, including C) as *integer division*: because we provide two integer numbers (`15` and `6`) to the division operator (`/`), the assumption is that we seek a return value of type integer. The mathematically correct answer is (the floating point number) 2.5. (→ numerical data types in [Chapter 13](13-numeric-computation.ipynb).)\n", "\n", "The convention for integer division is to truncate the fractional digits and to return the integer part only (i.e. `2` in this example). It is also called “floor division”.\n", "\n", "### How to avoid integer division\n", "\n", "There are two ways to avoid the problem of integer division:\n", "\n", "1. Use Python 3 style division: this is available even in Python 2 with a special import statement:\n", "\n", " ```python\n", " >>> from __future__ import division\n", " >>> 15/6\n", " 2.5\n", " ```\n", "\n", " If you want to use the `from __future__ import division` feature in a python program, it would normally be included at the beginning of the file.\n", "\n", "2. Alternatively, if we ensure that at least one number (numerator or denominator) is of type float (or complex), the division operator will return a floating point number. This can be done by writing `15.` instead of `15`, of by forcing conversion of the number to a float, i.e. use `float(15)` instead of `15`:\n", "\n", " ```python\n", " >>> 15./6\n", " 2.5\n", " >>> float(15)/6\n", " 2.5\n", " >>> 15/6.\n", " 2.5\n", " >>> 15/float(6)\n", " 2.5\n", " >>> 15./6.\n", " 2.5\n", " ```\n", "\n", "If we really want integer division, we can use `//`: `1//2` returns 0, in both Python 2 and 3." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Why should I care about this division problem?\n", "\n", "Integer division can result in surprising bugs: suppose you are writing code to compute the mean value *m* = (*x* + *y*)/2 of two numbers *x* and *y*. The first attempt of writing this may read:\n", "\n", "```python\n", "m = (x + y) / 2\n", "```\n", "\n", "Suppose this is tested with *x* = 0.5, *y* = 0.5, then the line above computes the correct answers *m* = 0.5 (because`0.5 + 0.5 = 1.0`, i.e. a 1.0 is a floating point number, and thus `1.0/2` evaluates to `0.5`). Or we could use *x* = 10, *y* = 30, and because `10 + 30 = 40` and `40/2` evaluates to `20`, we get the correct answer *m* = 20. However, if the integers *x* = 0 and *y* = 1 would come up, then the code returns *m* = 0 (because `0 + 1 = 1` and `1/2` evaluates to `0`) whereas *m* = 0.5 would have been the right answer.\n", "\n", "We have many possibilities to change the line of code above to work safely, including these three versions:\n", "\n", "```python\n", "m = (x + y) / 2.0\n", "\n", "m = float(x + y) / 2\n", "\n", "m = (x + y) * 0.5\n", "```\n", "\n", "This integer division behaviour is common amongst most programming languages (including the important ones C, C++ and Fortran), and it is important to be aware of the issue.\n", "\n", "Mathematical functions\n", "----------------------\n", "\n", "Because Python is a general purpose programming language, commonly used mathematical functions such as sin, cos, exp, log and many others are located in the mathematics module with name `math`. We can make use of this as soon as we *import* the math module:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "2.718281828459045" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import math\n", "math.exp(1.0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using the `dir` function, we can see the directory of objects available in the math module:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "['__doc__',\n", " '__file__',\n", " '__loader__',\n", " '__name__',\n", " '__package__',\n", " '__spec__',\n", " 'acos',\n", " 'acosh',\n", " 'asin',\n", " 'asinh',\n", " 'atan',\n", " 'atan2',\n", " 'atanh',\n", " 'ceil',\n", " 'copysign',\n", " 'cos',\n", " 'cosh',\n", " 'degrees',\n", " 'e',\n", " 'erf',\n", " 'erfc',\n", " 'exp',\n", " 'expm1',\n", " 'fabs',\n", " 'factorial',\n", " 'floor',\n", " 'fmod',\n", " 'frexp',\n", " 'fsum',\n", " 'gamma',\n", " 'hypot',\n", " 'isfinite',\n", " 'isinf',\n", " 'isnan',\n", " 'ldexp',\n", " 'lgamma',\n", " 'log',\n", " 'log10',\n", " 'log1p',\n", " 'log2',\n", " 'modf',\n", " 'pi',\n", " 'pow',\n", " 'radians',\n", " 'sin',\n", " 'sinh',\n", " 'sqrt',\n", " 'tan',\n", " 'tanh',\n", " 'trunc']" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dir(math)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As usual, the `help` function can provide more information about the module (`help(math)`) on individual objects:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function exp in module math:\n", "\n", "exp(...)\n", " exp(x)\n", " \n", " Return e raised to the power of x.\n", "\n" ] } ], "source": [ "help(math.exp)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The mathematics module defines to constants *π* and *e*:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "3.141592653589793" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "math.pi" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "2.718281828459045" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "math.e" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "-1.0" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "math.cos(math.pi)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "1.0" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "math.log(math.e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Variables\n", "---------\n", "\n", "A *variable* can be used to store a certain value or object. In Python, all numbers (and everything else, including functions, modules and files) are objects. A variable is created through assignement:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": true }, "outputs": [], "source": [ "x = 0.5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once the variable `x` has been created through assignment of 0.5 in this example, we can make use of it:" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "1.5" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x*3" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0.25" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x**2" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "333" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y = 111\n", "y + 222" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A variable is overriden if a new value is assigned:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "1.0" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y = 0.7\n", "math.sin(y) ** 2 + math.cos(y) ** 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The equal sign (’=’) is used to assign a value to a variable." ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "900" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "width = 20\n", "height = 5 * 9\n", "width * height" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A value can be assigned to several variables simultaneously:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = y = z = 0 # initialise x, y and z with 0\n", "x" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "z" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Variables must be created (assigned a value) before they can be used, or an error will occur:" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "collapsed": false }, "outputs": [ { "ename": "NameError", "evalue": "name 'n' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# try to access an undefined variable\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mn\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mNameError\u001b[0m: name 'n' is not defined" ] } ], "source": [ "# try to access an undefined variable\n", "n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In interactive mode, the last printed expression is assigned to the variable `_`. This means that when you are using Python as a desk calculator, it is somewhat easier to continue calculations, for example:" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "12.5625" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tax = 12.5 / 100\n", "price = 100.50\n", "price * tax" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "113.0625" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "price + _" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This variable should be treated as read-only by the user. Don’t explicitly assign a value to it — you would create an independent local variable with the same name masking the built-in variable with its magic behavior.\n", "\n", "### Terminology\n", "\n", "Strictly speaking, the following happens when we write" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "collapsed": true }, "outputs": [], "source": [ "x = 0.5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First, Python creates the object `0.5`. Everything in Python is an object, and so is the floating point number 0.5. This object is stored somewhere in memory. Next, Python *binds a name to the object*. The name is `x`, and we often refer casually to `x` as a variable, an object, or even the value 0.5. However, technically, `x` is a name that is bound to the object `0.5`. Another way to say this is that `x` is a reference to the object.\n", "\n", "While it is often sufficient to think about assigning 0.5 to a variable x, there are situations where we need to remember what actually happens. In particular, when we pass references to objects to functions, we need to realise that the function may operate on the object (rather than a copy of the object). This is discussed in more detail in [the next chapter](03-data-types-structures.ipynb).\n", "\n", "Impossible equations\n", "--------------------\n", "\n", "In computer programs we often find statements like" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "collapsed": true }, "outputs": [], "source": [ "x = x + 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we read this as an equation as we are use to from mathematics,\n", "*x* = *x* + 1\n", " we could subtract *x* on both sides, to find that\n", "0 = 1.\n", " We know this is not true, so something is wrong here.\n", "\n", "The answer is that “equations“ in computer codes are not equations but *assignments*. They always have to be read in the following way two-step way:\n", "\n", "1. Evaluate the value on the right hand side of the equal sign\n", "\n", "2. Assign this value to the variable name shown on the left hand side. (In Python: bind the name on the left hand side to the object shown on the right hand side.)\n", "\n", "Some computer science literature uses the following notation to express assignments and to avoid the confusion with mathematical equations:\n", "\n", "$$x \\leftarrow x + 1$$\n", "\n", "Let’s apply our two-step rule to the assignment `x = x + 1` given above:\n", "\n", "1. Evaluate the value on the right hand side of the equal sign: for this we need to know what the current value of `x` is. Let’s assume `x` is currently `4`. In that case, the right hand side `x+1` evaluates to `5`.\n", "\n", "2. Assign this value (i.e. `5`) to the variable name shown on the left hand side `x`.\n", "\n", "Let’s confirm with the Python prompt that this is the correct interpretation:" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = 4 \n", "x = x + 1\n", "x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### The `+=` notation\n", "\n", "Because it is a quite a common operation to increase a variable `x` by some fixed amount `c`, we can write\n", "\n", "```python\n", "x += c\n", "```\n", "\n", "instead of\n", "\n", "```python\n", "x = x + c\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Our initial example above could thus have been written" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = 4\n", "x += 1\n", "x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The same operators are defined for multiplication with a constant (`*=`), subtraction of a constant (`-=`) and division by a constant (`/=`).\n", "\n", "Note that the order of `+` and `=` matters:" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "collapsed": true }, "outputs": [], "source": [ "x += 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "will increase the variable `x` by one where as" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "collapsed": true }, "outputs": [], "source": [ "x =+ 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "will assign the value `+1` to the variable `x`." ] } ], "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.4.4" } }, "nbformat": 4, "nbformat_minor": 1 }