{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from __future__ import print_function" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Jupyter" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We'll be using Jupyter for all of our examples -- this allows us to run python in a web-based notebook, keeping a history of input and output, along with text and images.\n", "\n", "For Jupyter help, visit:\n", "https://jupyter.readthedocs.io/en/latest/content-quickstart.html" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We interact with python by typing into _cells_ in the notebook. By default, a cell is a _code_ cell, which means that you can enter any valid python code into it and run it. Another important type of cell is a _markdown_ cell. This lets you put text, with different formatting (italics, bold, etc) that describes what the notebook is doing.\n", "\n", "You can change the cell type via the menu at the top, or using the shortcuts:\n", "\n", " * ctrl-m m : mark down cell\n", " * ctrl-m y : code cell" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Some useful short-cuts:\n", "\n", " * shift+enter = run cell and jump to the next (creating a new cell if there is no other new one)\n", " * ctrl+enter = run cell-in place\n", " * alt+enter = run cell and insert a new one below\n", "\n", "ctrl+m h lists other commands" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A \"markdown cell\" enables you to typeset LaTeX equations right in your notebook. Just put them in $ or $$:\n", "\n", "$$\\frac{\\partial \\rho}{\\partial t} + \\nabla \\cdot (\\rho U) = 0$$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "**Important**: when you work through a notebook, everything you did in previous cells is still in memory and _known_ by python, so you can refer to functions and variables that were previously defined. Even if you go up to the top of a notebook and insert a cell, all the information done earlier in your notebook session is still defined -- it doesn't matter where physically you are in the notebook. If you want to reset things, you can use the options under the _Kernel_ menu.\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Quick Exercise:

\n", "\n", "Create a new cell below this one. Make sure that it is a _code_ cell, and enter the following code and run it:\n", "```\n", "print(\"Hello, World\")\n", "```\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`print()` is a _function_ in python that takes arguments (in the `()`) and outputs to the screen. You can print multiple quantities at once like:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "print(1, 2, 3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Basic Datatypes\n", "\n", "Now we'll look at some of the basic datatypes in python -- these are analogous to what you will find in most programming languages, including numbers (integers and floating point), and strings.\n", "\n", "Some examples come from the python tutorial:\n", "http://docs.python.org/3/tutorial/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## integers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Integers are numbers without a decimal point. They can be positive or negative. Most programming languages use a finite-amount of memory to store a single integer, but in python will expand the amount of memory as necessary to store large integers.\n", "\n", "The basic operators, `+`, `-`, `*`, and `/` work with integers" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "2+2+3" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "2*-4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note: integer division is one place where python 2 and python 3 different\n", " \n", "In python 3.x, dividing 2 integers results in a float. In python 2.x, dividing 2 integers results in an integer. The latter is consistent with many strongly-typed programming languages (like Fortran or C), since the data-type of the result is the same as the inputs, but the former is more inline with our expectations" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "1/2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To get an integer result, we can use the // operator." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "1//2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python is a _dynamically-typed language_—this means that we do not need to declare the datatype of a variable before initializing it. \n", "\n", "Here we'll create a variable (think of it as a descriptive label that can refer to some piece of data). The `=` operator assigns a value to a variable. " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "a = 1\n", "b = 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Functions operate on variables and return a result. Here, `print()` will output to the screen." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "print(a+b)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "print(a*b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that variable names are case sensitive, so a and A are different" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "A = 2048" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "print(a, A)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here we initialize 3 variable all to `0`, but these are still distinct variables, so we can change one without affecting the others." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "x = y = z = 0" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "print(x, y, z)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "z = 1" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "print(x, y, z)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python has some built in help (and Jupyter/ipython has even more)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "help(x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "x?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Another function, `type()` returns the data type of a variable" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "print(type(x))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note in languages like Fortran and C, you specify the amount of memory an integer can take (usually 2 or 4 bytes). This puts a restriction on the largest size integer that can be represented. Python will adapt the size of the integer so you don't *overflow*" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "a = 12345678901234567890123456789012345123456789012345678901234567890\n", "print(a)\n", "print(a.bit_length())\n", "print(type(a))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## floating point" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "when operating with both floating point and integers, the result is promoted to a float. This is true of both python 2.x and 3.x" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "1./2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "but note the special integer division operator" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "1.//2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is important to understand that since there are infinitely many real numbers between any two bounds, on a computer we have to approximate this by a finite number. There is an IEEE standard for floating point that pretty much all languages and processors follow. \n", "\n", "The means two things\n", "\n", "* not every real number will have an exact representation in floating point\n", "* there is a finite precision to numbers -- below this we lose track of differences (this is usually called *roundoff* error)\n", "\n", "On our course website, I posted a link to a paper, _What every computer scientist should know about floating-point arithmetic_ -- this is a great reference on understanding how a computer stores numbers.\n", "\n", "Consider the following expression, for example:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "0.3/0.1 - 3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here's another example: The number 0.1 cannot be exactly represented on a computer. In our print, we use a format specifier (the stuff inside of the {}) to ask for more precision to be shown:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "a = 0.1\n", "print(\"{:30.20}\".format(a))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "we can ask python to report the limits on floating point" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import sys\n", "print(sys.float_info)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that this says that we can only store numbers between 2.2250738585072014e-308 and 1.7976931348623157e+308\n", "\n", "We also see that the precision is 2.220446049250313e-16 (this is commonly called _machine epsilon_). To see this, consider adding a small number to 1.0. We'll use the equality operator (`==`) to test if two numbers are equal:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Quick Exercise:

\n", "\n", "Define two variables, $a = 1$, and $e = 10^{-16}$.\n", "\n", "Now define a third variable, `b = a + e`\n", "\n", "We can use the python `==` operator to test for equality. What do you expect `b == a` to return? run it an see if it agrees with your guess.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## modules\n", "\n", "The core python language is extended by a standard library that provides additional functionality. These added pieces are in the form of modules that we can _import_ into our python session (or program).\n", "\n", "The `math` module provides functions that do the basic mathematical operations as well as provide constants (note there is a separate `cmath` module for complex numbers).\n", "\n", "In python, you `import` a module. The functions are then defined in a separate _namespace_—this is a separate region that defines names and variables, etc. A variable in one namespace can have the same name as a variable in a different namespace, and they don't clash. You use the \"`.`\" operator to access a member of a namespace.\n", "\n", "By default, when you type stuff into the python interpreter or here in the Jupyter notebook, or in a script, it is in its own default namespace, and you don't need to prefix any of the variables with a namespace indicator." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import math" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`math` provides the value of pi" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print(math.pi)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is distinct from any variable `pi` we might define here" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "pi = 3" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print(pi, math.pi)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note here that `pi` and `math.pi` are distinct from one another—they are in different namespaces." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### floating point operations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The same operators, `+`, `-`, `*`, `/` work are usual for floating point numbers. To raise an number to a power, we use the `**` operator (this is the same as Fortran)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "R = 2.0" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print(math.pi*R**2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "operator precedence follows that of most languages. See\n", "\n", "https://docs.python.org/3/reference/expressions.html#operator-precedence\n", " \n", "in order of precedence:\n", "* quantites in `()`\n", "* slicing, calls, subscripts\n", "* exponentiation (`**`)\n", "* `+x`, `-x`, `~x`\n", "* `*`, `@`, `/`, `//`, `%`\n", "* `+`, `-`\n", "\n", "(after this are bitwise operations and comparisons)\n", "\n", "Parantheses can be used to override the precedence." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Quick Exercise:

\n", "\n", "Consider the following expressions. Using the ideas of precedence, think about what value will result, then try it out in the cell below to see if you were right.\n", "\n", " * `1 + 3*2**2`\n", " * `1 + (3*2)**2`\n", " * `2**3**2`\n", "\n", "
" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "2**(3**2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The math module provides a lot of the standard math functions we might want to use.\n", "\n", "For the trig functions, the expectation is that the argument to the function is in radians—you can use `math.radians()` to convert from degrees to radians, ex:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print(math.cos(math.radians(45)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that in that statement we are feeding the output of one function (`math.radians()`) into a second function, `math.cos()`\n", "\n", "When in doubt, as for help to discover all of the things a module provides:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "help(math.sin)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## complex numbers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "python uses '`j`' to denote the imaginary unit" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print(1.0 + 2j)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "a = 1j\n", "b = 3.0 + 2.0j\n", "print(a + b)\n", "print(a*b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "we can use `abs()` to get the magnitude and separately get the real or imaginary parts " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print(abs(b))\n", "print(a.real)\n", "print(a.imag)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## strings" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "python doesn't care if you use single or double quotes for strings:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "a = \"this is my string\"\n", "b = 'another string'" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print(a)\n", "print(b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Many of the usual mathematical operators are defined for strings as well. For example to concatenate or duplicate:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print(a+b)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print(a + \". \" + b)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print(a*2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are several escape codes that are interpreted in strings. These start with a backwards-slash, `\\`. E.g., you can use `\\n` for new line" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "a = a + \"\\n\"\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Quick Exercise:

\n", "\n", "The `input()` function can be used to ask the user for input.\n", "\n", " * Use `help(input)` to see how it works. \n", " * Write code to ask for input and store the result in a variable. `input()` will return a string.\n", "\n", " * Use the `float()` function to convert a number entered as input to a floating point variable. \n", " * Check to see if the conversion worked using the `type()` function.\n", "
" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "a = input(\"enter a string\")\n", "print(type(float(a)))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\"\"\" can enclose multiline strings. This is useful for docstrings at the start of functions (more on that later...)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "c = \"\"\"\n", "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor \n", "incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis \n", "nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \n", "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore \n", "eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt \n", "in culpa qui officia deserunt mollit anim id est laborum.\"\"\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "a raw string does not replace escape sequences (like \\n). Just put a `r` before the first quote:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "d = r\"this is a raw string\\n\"\n", "print(d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "slicing is used to access a portion of a string.\n", "\n", "slicing a string can seem a bit counterintuitive if you are coming from Fortran. The trick is to think of the index as representing the left edge of a character in the string. When we do arrays later, the same will apply.\n", "\n", "Also note that python (like C) uses 0-based indexing\n", "\n", "Negative indices count from the right." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "a = \"this is my string\"\n", "print(a)\n", "print(a[5:7])\n", "print(a[0])\n", "print(d)\n", "print(d[-2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Quick Exercise:

\n", "\n", "Strings have a lot of _methods_ (functions that know how to work with a particular datatype, in this case strings). A useful method is `.find()`. For a string `a`,\n", "`a.find(s)` will return the index of the first occurrence of `s`.\n", "\n", "For our string `c` above, find the first `.` (identifying the first full sentence), and print out just the first sentence in `c` using this result\n", "\n", "
" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "there are also a number of methods and functions that work with strings. Here are some examples:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print(a.replace(\"this\", \"that\"))\n", "print(len(a))\n", "print(a.strip()) # Also notice that strip removes the \\n\n", "print(a.strip()[-1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that our original string, `a`, has not changed. In python, strings are *immutable*. Operations on strings return a new string." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print(a)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "print(type(a))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As usual, ask for help to learn more:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "help(str)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can format strings when we are printing to insert quantities in particular places in the string. A `{}` serves as a placeholder for a quantity and is replaced using the `.format()` method:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "a = 1\n", "b = 2.0\n", "c = \"test\"\n", "print(\"a = {}; b = {}; c = {}\".format(a, b, c))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "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.5.3" } }, "nbformat": 4, "nbformat_minor": 1 }