├── .gitignore ├── .gitmodules ├── 00-Introduction.ipynb ├── 01-How-to-Run-Python-Code.ipynb ├── 02-Basic-Python-Syntax.ipynb ├── 03-Semantics-Variables.ipynb ├── 04-Semantics-Operators.ipynb ├── 05-Built-in-Scalar-Types.ipynb ├── 06-Built-in-Data-Structures.ipynb ├── 07-Control-Flow-Statements.ipynb ├── 08-Defining-Functions.ipynb ├── 09-Errors-and-Exceptions.ipynb ├── 10-Iterators.ipynb ├── 11-List-Comprehensions.ipynb ├── 12-Generators.ipynb ├── 13-Modules-and-Packages.ipynb ├── 14-Strings-and-Regular-Expressions.ipynb ├── 15-Preview-of-Data-Science-Tools.ipynb ├── 16-Further-Resources.ipynb ├── 17-Figures.ipynb ├── Index.ipynb ├── LICENSE ├── README.md ├── fig ├── cover-large.gif ├── cover-small.jpg └── list-indexing.png ├── tools ├── add_book_info.py └── add_navigation.py └── website ├── .gitignore ├── Makefile ├── README.md ├── content └── favicon.ico ├── copy_notebooks.py ├── fabfile.py ├── pelicanconf.py ├── publishconf.py └── theme ├── README.md ├── static ├── css │ └── icons.css └── font │ ├── icons.eot │ ├── icons.svg │ ├── icons.ttf │ └── icons.woff └── templates ├── _includes ├── analytics.html └── disqus_thread.html ├── about.html ├── archives.html ├── article.html ├── base.html ├── booksection.html ├── index.html ├── ipynb.css ├── main.css ├── main.less ├── page.html ├── pygments.css └── tag.html /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | local_settings.py 55 | 56 | # Flask stuff: 57 | instance/ 58 | .webassets-cache 59 | 60 | # Scrapy stuff: 61 | .scrapy 62 | 63 | # Sphinx documentation 64 | docs/_build/ 65 | 66 | # PyBuilder 67 | target/ 68 | 69 | # IPython Notebook 70 | .ipynb_checkpoints 71 | 72 | # pyenv 73 | .python-version 74 | 75 | # celery beat schedule file 76 | celerybeat-schedule 77 | 78 | # dotenv 79 | .env 80 | 81 | # virtualenv 82 | venv/ 83 | ENV/ 84 | 85 | # Spyder project settings 86 | .spyderproject 87 | 88 | # Rope project settings 89 | .ropeproject 90 | 91 | 92 | # emacs 93 | *~ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "website/plugins/ipynb"] 2 | path = website/plugins/ipynb 3 | url = git://github.com/danielfrg/pelican-ipynb.git 4 | [submodule "website/plugins/pelican-plugins"] 5 | path = website/plugins/pelican-plugins 6 | url = git://github.com/getpelican/pelican-plugins.git 7 | -------------------------------------------------------------------------------- /00-Introduction.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "*This notebook contains an excerpt from the [Whirlwind Tour of Python](http://www.oreilly.com/programming/free/a-whirlwind-tour-of-python.csp) by Jake VanderPlas; the content is available [on GitHub](https://github.com/jakevdp/WhirlwindTourOfPython).*\n", 10 | "\n", 11 | "*The text and code are released under the [CC0](https://github.com/jakevdp/WhirlwindTourOfPython/blob/master/LICENSE) license; see also the companion project, the [Python Data Science Handbook](https://github.com/jakevdp/PythonDataScienceHandbook).*\n" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "\n", 19 | "| [Contents](Index.ipynb) | [How to Run Python Code](01-How-to-Run-Python-Code.ipynb) >" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "# 1. Introduction" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "Conceived in the late 1980s as a teaching and scripting language, Python has since become an essential tool for many programmers, engineers, researchers, and data scientists across academia and industry.\n", 34 | "As an astronomer focused on building and promoting the free open tools for data-intensive science, I've found Python to be a near-perfect fit for the types of problems I face day to day, whether it's extracting meaning from large astronomical datasets, scraping and munging data sources from the Web, or automating day-to-day research tasks.\n", 35 | "\n", 36 | "The appeal of Python is in its simplicity and beauty, as well as the convenience of the large ecosystem of domain-specific tools that have been built on top of it.\n", 37 | "For example, most of the Python code in scientific computing and data science is built around a group of mature and useful packages:\n", 38 | "\n", 39 | "- [NumPy](http://numpy.org) provides efficient storage and computation for multi-dimensional data arrays.\n", 40 | "- [SciPy](http://scipy.org) contains a wide array of numerical tools such as numerical integration and interpolation.\n", 41 | "- [Pandas](http://pandas.pydata.org) provides a DataFrame object along with a powerful set of methods to manipulate, filter, group, and transform data.\n", 42 | "- [Matplotlib](http://matplotlib.org) provides a useful interface for creation of publication-quality plots and figures.\n", 43 | "- [Scikit-Learn](http://scikit-learn.org) provides a uniform toolkit for applying common machine learning algorithms to data.\n", 44 | "- [IPython/Jupyter](http://jupyter.org) provides an enhanced terminal and an interactive notebook environment that is useful for exploratory analysis, as well as creation of interactive, executable documents. For example, the manuscript for this report was composed entirely in Jupyter notebooks.\n", 45 | "\n", 46 | "No less important are the numerous other tools and packages which accompany these: if there is a scientific or data analysis task you want to perform, chances are someone has written a package that will do it for you.\n", 47 | "\n", 48 | "To tap into the power of this data science ecosystem, however, first requires familiarity with the Python language itself.\n", 49 | "I often encounter students and colleagues who have (sometimes extensive) backgrounds in computing in some language – MATLAB, IDL, R, Java, C++, etc. – and are looking for a brief but comprehensive tour of the Python language that respects their level of knowledge rather than starting from ground zero.\n", 50 | "This report seeks to fill that niche.\n", 51 | "\n", 52 | "As such, this report in no way aims to be a comprehensive introduction to programming, or a full introduction to the Python language itself; if that is what you are looking for, you might check out one of the recommended references listed in [Resources for Learning](16-Further-Resources.ipynb).\n", 53 | "Instead, this will provide a whirlwind tour of some of Python's essential syntax and semantics, built-in data types and structures, function definitions, control flow statements, and other aspects of the language.\n", 54 | "My aim is that readers will walk away with a solid foundation from which to explore the data science stack just outlined." 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "metadata": {}, 60 | "source": [ 61 | "## Using Code Examples\n", 62 | "\n", 63 | "Supplemental material (code examples, exercises, etc.) is available for download at https://github.com/jakevdp/WhirlwindTourOfPython/.\n", 64 | "This book is here to help you get your job done.\n", 65 | "In general, if example code is offered with this book, you may use it in your programs and documentation.\n", 66 | "You do not need to contact us for permission unless you’re reproducing a significant portion of the code.\n", 67 | "For example, writing a program that uses several chunks of code from this book does not require permission.\n", 68 | "Selling or distributing a CD-ROM of examples from O’Reilly books does require permission.\n", 69 | "Answering a question by citing this book and quoting example code does not require permission.\n", 70 | "Incorporating a significant amount of example code from this book into your product’s documentation does require permission.\n", 71 | "\n", 72 | "We appreciate, but do not require, attribution.\n", 73 | "An attribution usually includes the title, author, publisher, and ISBN.\n", 74 | "For example: \"A Whirlwind Tour of Python by Jake VanderPlas (O’Reilly). Copyright 2016 O’Reilly Media, Inc., 978-1-491-96465-1.\"\n", 75 | "\n", 76 | "If you feel your use of code examples falls outside fair use or the per‐ mission given above, feel free to contact us at permissions@oreilly.com." 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": {}, 82 | "source": [ 83 | "## Installation and Practical Considerations\n", 84 | "\n", 85 | "Installing Python and the suite of libraries that enable scientific computing is straightforward whether you use Windows, Linux, or Mac OS X. This section will outline some of the considerations when setting up your computer." 86 | ] 87 | }, 88 | { 89 | "cell_type": "markdown", 90 | "metadata": {}, 91 | "source": [ 92 | "### Python 2 vs Python 3\n", 93 | "\n", 94 | "This report uses the syntax of Python 3, which contains language enhancements that are not compatible with the *2.x* series of Python.\n", 95 | "Though Python 3.0 was first released in 2008, adoption has been relatively slow, particularly in the scientific and web development communities.\n", 96 | "This is primarily because it took some time for many of the essential packages and toolkits to be made compatible with the new language internals.\n", 97 | "Since early 2014, however, stable releases of the most important tools in the data science ecosystem have been fully-compatible with both Python 2 and 3, and so this book will use the newer Python 3 syntax.\n", 98 | "Even though that is the case, the vast majority of code snippets in this book will also work without modification in Python 2: in cases where a Py2-incompatible syntax is used, I will make every effort to note it explicitly." 99 | ] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": {}, 104 | "source": [ 105 | "### Installation with conda\n", 106 | "\n", 107 | "Though there are various ways to install Python, the one I would suggest – particularly if you wish to eventually use the data science tools mentioned above – is via the cross-platform Anaconda distribution.\n", 108 | "There are two flavors of the Anaconda distribution:\n", 109 | "\n", 110 | "- [Miniconda](http://conda.pydata.org/miniconda.html) gives you Python interpreter itself, along with a command-line tool called ``conda`` which operates as a cross-platform package manager geared toward Python packages, similar in spirit to the ``apt`` or ``yum`` tools that Linux users might be familiar with.\n", 111 | "- [Anaconda](https://www.continuum.io/downloads) includes both Python and ``conda``, and additionally bundles a suite of other pre-installed packages geared toward scientific computing.\n", 112 | "\n", 113 | "Any of the packages included with Anaconda can also be installed manually on top of Miniconda; for this reason I suggest starting with Miniconda.\n", 114 | "\n", 115 | "To get started, download and install the Miniconda package – make sure to choose a version with Python 3 – and then install the IPython notebook package:\n", 116 | "```\n", 117 | "[~]$ conda install ipython-notebook\n", 118 | "```\n", 119 | "For more information on ``conda``, including information about creating and using conda environments, refer to the Miniconda package documentation linked at the above page." 120 | ] 121 | }, 122 | { 123 | "cell_type": "markdown", 124 | "metadata": {}, 125 | "source": [ 126 | "## The Zen of Python\n", 127 | "\n", 128 | "Python aficionados are often quick to point out how \"intuitive\", \"beautiful\", or \"fun\" Python is.\n", 129 | "While I tend to agree, I also recognize that beauty, intuition, and fun often go hand in hand with familiarity, and so for those familiar with other languages such florid sentiments can come across as a bit smug.\n", 130 | "Nevertheless, I hope that if you give Python a chance, you'll see where such impressions might come from.\n", 131 | "And if you *really* want to dig into the programming philosophy that drives much of the coding practice of Python power-users, a nice little Easter egg exists in the Python interpreter: simply close your eyes, meditate for a few minutes, and ``import this``:" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "execution_count": 1, 137 | "metadata": { 138 | "collapsed": false 139 | }, 140 | "outputs": [ 141 | { 142 | "name": "stdout", 143 | "output_type": "stream", 144 | "text": [ 145 | "The Zen of Python, by Tim Peters\n", 146 | "\n", 147 | "Beautiful is better than ugly.\n", 148 | "Explicit is better than implicit.\n", 149 | "Simple is better than complex.\n", 150 | "Complex is better than complicated.\n", 151 | "Flat is better than nested.\n", 152 | "Sparse is better than dense.\n", 153 | "Readability counts.\n", 154 | "Special cases aren't special enough to break the rules.\n", 155 | "Although practicality beats purity.\n", 156 | "Errors should never pass silently.\n", 157 | "Unless explicitly silenced.\n", 158 | "In the face of ambiguity, refuse the temptation to guess.\n", 159 | "There should be one-- and preferably only one --obvious way to do it.\n", 160 | "Although that way may not be obvious at first unless you're Dutch.\n", 161 | "Now is better than never.\n", 162 | "Although never is often better than *right* now.\n", 163 | "If the implementation is hard to explain, it's a bad idea.\n", 164 | "If the implementation is easy to explain, it may be a good idea.\n", 165 | "Namespaces are one honking great idea -- let's do more of those!\n" 166 | ] 167 | } 168 | ], 169 | "source": [ 170 | "import this" 171 | ] 172 | }, 173 | { 174 | "cell_type": "markdown", 175 | "metadata": {}, 176 | "source": [ 177 | "With that, let's start our tour of the Python language." 178 | ] 179 | }, 180 | { 181 | "cell_type": "markdown", 182 | "metadata": {}, 183 | "source": [ 184 | "\n", 185 | "| [Contents](Index.ipynb) | [How to Run Python Code](01-How-to-Run-Python-Code.ipynb) >" 186 | ] 187 | } 188 | ], 189 | "metadata": { 190 | "anaconda-cloud": {}, 191 | "kernelspec": { 192 | "display_name": "Python 3", 193 | "language": "python", 194 | "name": "python3" 195 | }, 196 | "language_info": { 197 | "codemirror_mode": { 198 | "name": "ipython", 199 | "version": 3 200 | }, 201 | "file_extension": ".py", 202 | "mimetype": "text/x-python", 203 | "name": "python", 204 | "nbconvert_exporter": "python", 205 | "pygments_lexer": "ipython3", 206 | "version": "3.5.1" 207 | } 208 | }, 209 | "nbformat": 4, 210 | "nbformat_minor": 0 211 | } 212 | -------------------------------------------------------------------------------- /01-How-to-Run-Python-Code.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "*This notebook contains an excerpt from the [Whirlwind Tour of Python](http://www.oreilly.com/programming/free/a-whirlwind-tour-of-python.csp) by Jake VanderPlas; the content is available [on GitHub](https://github.com/jakevdp/WhirlwindTourOfPython).*\n", 10 | "\n", 11 | "*The text and code are released under the [CC0](https://github.com/jakevdp/WhirlwindTourOfPython/blob/master/LICENSE) license; see also the companion project, the [Python Data Science Handbook](https://github.com/jakevdp/PythonDataScienceHandbook).*\n" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "\n", 19 | "< [1. Introduction](00-Introduction.ipynb) | [Contents](Index.ipynb) | [A Quick Tour of Python Language Syntax](02-Basic-Python-Syntax.ipynb) >" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "# How to Run Python Code" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "Python is a flexible language, and there are several ways to use it depending on your particular task.\n", 34 | "One thing that distinguishes Python from other programming languages is that it is *interpreted* rather than *compiled*.\n", 35 | "This means that it is executed line by line, which allows programming to be interactive in a way that is not directly possible with compiled languages like Fortran, C, or Java. This section will describe four primary ways you can run Python code: the *Python interpreter*, the *IPython interpreter*, via *Self-contained Scripts*, or in the *Jupyter notebook*." 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "### The Python Interpreter\n", 43 | "\n", 44 | "The most basic way to execute Python code is line by line within the *Python interpreter*.\n", 45 | "The Python interpreter can be started by installing the Python language (see the previous section) and typing ``python`` at the command prompt (look for the Terminal on Mac OS X and Unix/Linux systems, or the Command Prompt application in Windows):\n", 46 | "```\n", 47 | "$ python\n", 48 | "Python 3.5.1 |Continuum Analytics, Inc.| (default, Dec 7 2015, 11:24:55)\n", 49 | "Type \"help\", \"copyright\", \"credits\" or \"license\" for more information.\n", 50 | ">>>\n", 51 | "```\n", 52 | "With the interpreter running, you can begin to type and execute code snippets.\n", 53 | "Here we'll use the interpreter as a simple calculator, performing calculations and assigning values to variables:\n", 54 | "``` python\n", 55 | ">>> 1 + 1\n", 56 | "2\n", 57 | ">>> x = 5\n", 58 | ">>> x * 3\n", 59 | "15\n", 60 | "```\n", 61 | "\n", 62 | "The interpreter makes it very convenient to try out small snippets of Python code and to experiment with short sequences of operations." 63 | ] 64 | }, 65 | { 66 | "cell_type": "markdown", 67 | "metadata": {}, 68 | "source": [ 69 | "### The IPython interpreter\n", 70 | "\n", 71 | "If you spend much time with the basic Python interpreter, you'll find that it lacks many of the features of a full-fledged interactive development environment.\n", 72 | "An alternative interpreter called *IPython* (for Interactive Python) is bundled with the Anaconda distribution, and includes a host of convenient enhancements to the basic Python interpreter.\n", 73 | "It can be started by typing ``ipython`` at the command prompt:\n", 74 | "```\n", 75 | "$ ipython\n", 76 | "Python 3.5.1 |Continuum Analytics, Inc.| (default, Dec 7 2015, 11:24:55) \n", 77 | "Type \"copyright\", \"credits\" or \"license\" for more information.\n", 78 | "\n", 79 | "IPython 4.0.0 -- An enhanced Interactive Python.\n", 80 | "? -> Introduction and overview of IPython's features.\n", 81 | "%quickref -> Quick reference.\n", 82 | "help -> Python's own help system.\n", 83 | "object? -> Details about 'object', use 'object??' for extra details.\n", 84 | "\n", 85 | "In [1]: \n", 86 | "```\n", 87 | "The main aesthetic difference between the Python interpreter and the enhanced IPython interpreter lies in the command prompt: Python uses ``>>>`` by default, while IPython uses numbered commands (e.g. ``In [1]:``).\n", 88 | "Regardless, we can execute code line by line just as we did before:\n", 89 | "``` ipython\n", 90 | "In [1]: 1 + 1\n", 91 | "Out[1]: 2\n", 92 | "\n", 93 | "In [2]: x = 5\n", 94 | "\n", 95 | "In [3]: x * 3\n", 96 | "Out[3]: 15\n", 97 | "```\n", 98 | "Note that just as the input is numbered, the output of each command is numbered as well.\n", 99 | "IPython makes available a wide array of useful features; for some suggestions on where to read more, see [Resources for Further Learning](16-Further-Resources.ipynb)." 100 | ] 101 | }, 102 | { 103 | "cell_type": "markdown", 104 | "metadata": {}, 105 | "source": [ 106 | "### Self-contained Python scripts\n", 107 | "\n", 108 | "Running Python snippets line by line is useful in some cases, but for more complicated programs it is more convenient to save code to file, and execute it all at once.\n", 109 | "By convention, Python scripts are saved in files with a *.py* extension.\n", 110 | "For example, let's create a script called *test.py* which contains the following:\n", 111 | "``` python\n", 112 | "# file: test.py\n", 113 | "print(\"Running test.py\")\n", 114 | "x = 5\n", 115 | "print(\"Result is\", 3 * x)\n", 116 | "```\n", 117 | "To run this file, we make sure it is in the current directory and type ``python`` *``filename``* at the command prompt:\n", 118 | "```\n", 119 | "$ python test.py\n", 120 | "Running test.py\n", 121 | "Result is 15\n", 122 | "```\n", 123 | "For more complicated programs, creating self-contained scripts like this one is a must." 124 | ] 125 | }, 126 | { 127 | "cell_type": "markdown", 128 | "metadata": {}, 129 | "source": [ 130 | "### The Jupyter notebook\n", 131 | "\n", 132 | "A useful hybrid of the interactive terminal and the self-contained script is the *Jupyter notebook*, a document format that allows executable code, formatted text, graphics, and even interactive features to be combined into a single document.\n", 133 | "Though the notebook began as a Python-only format, it has since been made compatible with a large number of programming languages, and is now an essential part of the [*Jupyter Project*](https://jupyter.org/).\n", 134 | "The notebook is useful both as a development environment, and as a means of sharing work via rich computational and data-driven narratives that mix together code, figures, data, and text." 135 | ] 136 | }, 137 | { 138 | "cell_type": "markdown", 139 | "metadata": {}, 140 | "source": [ 141 | "\n", 142 | "< [1. Introduction](00-Introduction.ipynb) | [Contents](Index.ipynb) | [A Quick Tour of Python Language Syntax](02-Basic-Python-Syntax.ipynb) >" 143 | ] 144 | } 145 | ], 146 | "metadata": { 147 | "anaconda-cloud": {}, 148 | "kernelspec": { 149 | "display_name": "Python 3", 150 | "language": "python", 151 | "name": "python3" 152 | }, 153 | "language_info": { 154 | "codemirror_mode": { 155 | "name": "ipython", 156 | "version": 3 157 | }, 158 | "file_extension": ".py", 159 | "mimetype": "text/x-python", 160 | "name": "python", 161 | "nbconvert_exporter": "python", 162 | "pygments_lexer": "ipython3", 163 | "version": "3.5.1" 164 | } 165 | }, 166 | "nbformat": 4, 167 | "nbformat_minor": 0 168 | } 169 | -------------------------------------------------------------------------------- /02-Basic-Python-Syntax.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "*This notebook contains an excerpt from the [Whirlwind Tour of Python](http://www.oreilly.com/programming/free/a-whirlwind-tour-of-python.csp) by Jake VanderPlas; the content is available [on GitHub](https://github.com/jakevdp/WhirlwindTourOfPython).*\n", 10 | "\n", 11 | "*The text and code are released under the [CC0](https://github.com/jakevdp/WhirlwindTourOfPython/blob/master/LICENSE) license; see also the companion project, the [Python Data Science Handbook](https://github.com/jakevdp/PythonDataScienceHandbook).*\n" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "\n", 19 | "< [How to Run Python Code](01-How-to-Run-Python-Code.ipynb) | [Contents](Index.ipynb) | [Basic Python Semantics: Variables and Objects](03-Semantics-Variables.ipynb) >" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "# A Quick Tour of Python Language Syntax" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "Python was originally developed as a teaching language, but its ease of use and clean syntax have led it to be embraced by beginners and experts alike.\n", 34 | "The cleanliness of Python's syntax has led some to call it \"executable pseudocode\", and indeed my own experience has been that it is often much easier to read and understand a Python script than to read a similar script written in, say, C.\n", 35 | "Here we'll begin to discuss the main features of Python's syntax.\n", 36 | "\n", 37 | "Syntax refers to the structure of the language (i.e., what constitutes a correctly-formed program).\n", 38 | "For the time being, we'll not focus on the semantics – the meaning of the words and symbols within the syntax – but will return to this at a later point.\n", 39 | "\n", 40 | "Consider the following code example:" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": 1, 46 | "metadata": { 47 | "collapsed": false 48 | }, 49 | "outputs": [ 50 | { 51 | "name": "stdout", 52 | "output_type": "stream", 53 | "text": [ 54 | "lower: [0, 1, 2, 3, 4]\n", 55 | "upper: [5, 6, 7, 8, 9]\n" 56 | ] 57 | } 58 | ], 59 | "source": [ 60 | "# set the midpoint\n", 61 | "midpoint = 5\n", 62 | "\n", 63 | "# make two empty lists\n", 64 | "lower = []; upper = []\n", 65 | "\n", 66 | "# split the numbers into lower and upper\n", 67 | "for i in range(10):\n", 68 | " if (i < midpoint):\n", 69 | " lower.append(i)\n", 70 | " else:\n", 71 | " upper.append(i)\n", 72 | " \n", 73 | "print(\"lower:\", lower)\n", 74 | "print(\"upper:\", upper)" 75 | ] 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "metadata": {}, 80 | "source": [ 81 | "This script is a bit silly, but it compactly illustrates several of the important aspects of Python syntax.\n", 82 | "Let's walk through it and discuss some of the syntactical features of Python" 83 | ] 84 | }, 85 | { 86 | "cell_type": "markdown", 87 | "metadata": {}, 88 | "source": [ 89 | "## Comments Are Marked by ``#``\n", 90 | "The script starts with a comment:\n", 91 | "``` python\n", 92 | "# set the midpoint\n", 93 | "```\n", 94 | "Comments in Python are indicated by a pound sign (``#``), and anything on the line following the pound sign is ignored by the interpreter.\n", 95 | "This means, for example, that you can have stand-alone comments like the one just shown, as well as inline comments that follow a statement. For example:\n", 96 | "``` python\n", 97 | "x += 2 # shorthand for x = x + 2\n", 98 | "```\n", 99 | "Python does not have any syntax for multi-line comments, such as the ``/* ... */`` syntax used in C and C++, though multi-line strings are often used as a replacement for multi-line comments (more on this in [String Manipulation and Regular Expressions](14-Strings-and-Regular-Expressions.ipynb))." 100 | ] 101 | }, 102 | { 103 | "cell_type": "markdown", 104 | "metadata": {}, 105 | "source": [ 106 | "## End-of-Line Terminates a Statement\n", 107 | "The next line in the script is\n", 108 | "``` python\n", 109 | "midpoint = 5\n", 110 | "```\n", 111 | "This is an assignment operation, where we've created a variable named ``midpoint`` and assigned it the value ``5``.\n", 112 | "Notice that the end of this statement is simply marked by the end of the line.\n", 113 | "This is in contrast to languages like C and C++, where every statement must end with a semicolon (``;``).\n", 114 | "\n", 115 | "In Python, if you'd like a statement to continue to the next line, it is possible to use the \"``\\``\" marker to indicate this:" 116 | ] 117 | }, 118 | { 119 | "cell_type": "code", 120 | "execution_count": 2, 121 | "metadata": { 122 | "collapsed": false 123 | }, 124 | "outputs": [], 125 | "source": [ 126 | "x = 1 + 2 + 3 + 4 +\\\n", 127 | " 5 + 6 + 7 + 8" 128 | ] 129 | }, 130 | { 131 | "cell_type": "markdown", 132 | "metadata": {}, 133 | "source": [ 134 | "It is also possible to continue expressions on the next line within parentheses, without using the \"``\\``\" marker:" 135 | ] 136 | }, 137 | { 138 | "cell_type": "code", 139 | "execution_count": 3, 140 | "metadata": { 141 | "collapsed": false 142 | }, 143 | "outputs": [], 144 | "source": [ 145 | "x = (1 + 2 + 3 + 4 +\n", 146 | " 5 + 6 + 7 + 8)" 147 | ] 148 | }, 149 | { 150 | "cell_type": "markdown", 151 | "metadata": {}, 152 | "source": [ 153 | "Most Python style guides recommend the second version of line continuation (within parentheses) to the first (use of the \"``\\``\" marker)." 154 | ] 155 | }, 156 | { 157 | "cell_type": "markdown", 158 | "metadata": {}, 159 | "source": [ 160 | "## Semicolon Can Optionally Terminate a Statement\n", 161 | "Sometimes it can be useful to put multiple statements on a single line.\n", 162 | "The next portion of the script is\n", 163 | "``` python\n", 164 | "lower = []; upper = []\n", 165 | "```\n", 166 | "This shows the example of how the semicolon (``;``) familiar in C can be used optionally in Python to put two statements on a single line.\n", 167 | "Functionally, this is entirely equivalent to writing\n", 168 | "``` python\n", 169 | "lower = []\n", 170 | "upper = []\n", 171 | "```\n", 172 | "Using a semicolon to put multiple statements on a single line is generally discouraged by most Python style guides, though occasionally it proves convenient." 173 | ] 174 | }, 175 | { 176 | "cell_type": "markdown", 177 | "metadata": {}, 178 | "source": [ 179 | "## Indentation: Whitespace Matters!\n", 180 | "Next, we get to the main block of code:\n", 181 | "``` Python\n", 182 | "for i in range(10):\n", 183 | " if i < midpoint:\n", 184 | " lower.append(i)\n", 185 | " else:\n", 186 | " upper.append(i)\n", 187 | "```\n", 188 | "This is a compound control-flow statement including a loop and a conditional – we'll look at these types of statements in a moment.\n", 189 | "For now, consider that this demonstrates what is perhaps the most controversial feature of Python's syntax: whitespace is meaningful!\n", 190 | "\n", 191 | "In programming languages, a *block* of code is a set of statements that should be treated as a unit.\n", 192 | "In C, for example, code blocks are denoted by curly braces:\n", 193 | "``` C\n", 194 | "// C code\n", 195 | "for(int i=0; i<100; i++)\n", 196 | " {\n", 197 | " // curly braces indicate code block\n", 198 | " total += i;\n", 199 | " }\n", 200 | "```\n", 201 | "In Python, code blocks are denoted by *indentation*:\n", 202 | "``` python\n", 203 | "for i in range(100):\n", 204 | " # indentation indicates code block\n", 205 | " total += i\n", 206 | "```\n", 207 | "In Python, indented code blocks are always preceded by a colon (``:``) on the previous line." 208 | ] 209 | }, 210 | { 211 | "cell_type": "markdown", 212 | "metadata": {}, 213 | "source": [ 214 | "The use of indentation helps to enforce the uniform, readable style that many find appealing in Python code.\n", 215 | "But it might be confusing to the uninitiated; for example, the following two snippets will produce different results:\n", 216 | "```python\n", 217 | ">>> if x < 4: >>> if x < 4:\n", 218 | "... y = x * 2 ... y = x * 2\n", 219 | "... print(x) ... print(x)\n", 220 | "```\n", 221 | "In the snippet on the left, ``print(x)`` is in the indented block, and will be executed only if ``x`` is less than ``4``.\n", 222 | "In the snippet on the right ``print(x)`` is outside the block, and will be executed regardless of the value of ``x``!" 223 | ] 224 | }, 225 | { 226 | "cell_type": "markdown", 227 | "metadata": {}, 228 | "source": [ 229 | "Python's use of meaningful whitespace often is surprising to programmers who are accustomed to other languages, but in practice it can lead to much more consistent and readable code than languages that do not enforce indentation of code blocks.\n", 230 | "If you find Python's use of whitespace disagreeable, I'd encourage you to give it a try: as I did, you may find that you come to appreciate it.\n", 231 | "\n", 232 | "Finally, you should be aware that the *amount* of whitespace used for indenting code blocks is up to the user, as long as it is consistent throughout the script.\n", 233 | "By convention, most style guides recommend to indent code blocks by four spaces, and that is the convention we will follow in this report.\n", 234 | "Note that many text editors like Emacs and Vim contain Python modes that do four-space indentation automatically." 235 | ] 236 | }, 237 | { 238 | "cell_type": "markdown", 239 | "metadata": {}, 240 | "source": [ 241 | "## Whitespace *Within* Lines Does Not Matter\n", 242 | "While the mantra of *meaningful whitespace* holds true for whitespace *before* lines (which indicate a code block), white space *within* lines of Python code does not matter.\n", 243 | "For example, all three of these expressions are equivalent:" 244 | ] 245 | }, 246 | { 247 | "cell_type": "code", 248 | "execution_count": 4, 249 | "metadata": { 250 | "collapsed": false 251 | }, 252 | "outputs": [], 253 | "source": [ 254 | "x=1+2\n", 255 | "x = 1 + 2\n", 256 | "x = 1 + 2" 257 | ] 258 | }, 259 | { 260 | "cell_type": "markdown", 261 | "metadata": {}, 262 | "source": [ 263 | "Abusing this flexibility can lead to issues with code readibility – in fact, abusing white space is often one of the primary means of intentionally obfuscating code (which some people do for sport).\n", 264 | "Using whitespace effectively can lead to much more readable code, \n", 265 | "especially in cases where operators follow each other – compare the following two expressions for exponentiating by a negative number:\n", 266 | "``` python\n", 267 | "x=10**-2\n", 268 | "```\n", 269 | "to\n", 270 | "``` python\n", 271 | "x = 10 ** -2\n", 272 | "```\n", 273 | "I find the second version with spaces much more easily readable at a single glance.\n", 274 | "Most Python style guides recommend using a single space around binary operators, and no space around unary operators.\n", 275 | "We'll discuss Python's operators further in [Basic Python Semantics: Operators](04-Semantics-Operators.ipynb)." 276 | ] 277 | }, 278 | { 279 | "cell_type": "markdown", 280 | "metadata": {}, 281 | "source": [ 282 | "## Parentheses Are for Grouping or Calling\n", 283 | "\n", 284 | "In the previous code snippet, we see two uses of parentheses.\n", 285 | "First, they can be used in the typical way to group statements or mathematical operations:" 286 | ] 287 | }, 288 | { 289 | "cell_type": "code", 290 | "execution_count": 5, 291 | "metadata": { 292 | "collapsed": false 293 | }, 294 | "outputs": [ 295 | { 296 | "data": { 297 | "text/plain": [ 298 | "14" 299 | ] 300 | }, 301 | "execution_count": 5, 302 | "metadata": {}, 303 | "output_type": "execute_result" 304 | } 305 | ], 306 | "source": [ 307 | "2 * (3 + 4)" 308 | ] 309 | }, 310 | { 311 | "cell_type": "markdown", 312 | "metadata": {}, 313 | "source": [ 314 | "They can also be used to indicate that a *function* is being called.\n", 315 | "In the next snippet, the ``print()`` function is used to display the contents of a variable (see the sidebar).\n", 316 | "The function call is indicated by a pair of opening and closing parentheses, with the *arguments* to the function contained within:" 317 | ] 318 | }, 319 | { 320 | "cell_type": "code", 321 | "execution_count": 6, 322 | "metadata": { 323 | "collapsed": false 324 | }, 325 | "outputs": [ 326 | { 327 | "name": "stdout", 328 | "output_type": "stream", 329 | "text": [ 330 | "first value: 1\n" 331 | ] 332 | } 333 | ], 334 | "source": [ 335 | "print('first value:', 1)" 336 | ] 337 | }, 338 | { 339 | "cell_type": "code", 340 | "execution_count": 7, 341 | "metadata": { 342 | "collapsed": false 343 | }, 344 | "outputs": [ 345 | { 346 | "name": "stdout", 347 | "output_type": "stream", 348 | "text": [ 349 | "second value: 2\n" 350 | ] 351 | } 352 | ], 353 | "source": [ 354 | "print('second value:', 2)" 355 | ] 356 | }, 357 | { 358 | "cell_type": "markdown", 359 | "metadata": {}, 360 | "source": [ 361 | "Some functions can be called with no arguments at all, in which case the opening and closing parentheses still must be used to indicate a function evaluation.\n", 362 | "An example of this is the ``sort`` method of lists:" 363 | ] 364 | }, 365 | { 366 | "cell_type": "code", 367 | "execution_count": 8, 368 | "metadata": { 369 | "collapsed": false 370 | }, 371 | "outputs": [ 372 | { 373 | "name": "stdout", 374 | "output_type": "stream", 375 | "text": [ 376 | "[1, 2, 3, 4]\n" 377 | ] 378 | } 379 | ], 380 | "source": [ 381 | "L = [4,2,3,1]\n", 382 | "L.sort()\n", 383 | "print(L)" 384 | ] 385 | }, 386 | { 387 | "cell_type": "markdown", 388 | "metadata": {}, 389 | "source": [ 390 | "The \"``()``\" after ``sort`` indicates that the function should be executed, and is required even if no arguments are necessary." 391 | ] 392 | }, 393 | { 394 | "cell_type": "markdown", 395 | "metadata": {}, 396 | "source": [ 397 | "## Aside: A Note on the ``print()`` Function\n", 398 | "\n", 399 | "Above we used the example of the ``print()`` function.\n", 400 | "The ``print()`` function is one piece that has changed between Python *2.x* and Python *3.x*. In Python 2, ``print`` behaved as a statement: that is, you could write\n", 401 | "``` python\n", 402 | "# Python 2 only!\n", 403 | ">> print \"first value:\", 1\n", 404 | "first value: 1\n", 405 | "```\n", 406 | "For various reasons, the language maintainers decided that in Python 3 ``print()`` should become a function, so we now write\n", 407 | "``` python\n", 408 | "# Python 3 only!\n", 409 | ">>> print(\"first value:\", 1)\n", 410 | "first value: 1\n", 411 | "```\n", 412 | "This is one of the many backward-incompatible constructs between Python 2 and 3.\n", 413 | "As of the writing of this book, it is common to find examples written in both versions of Python, and the presence of the ``print`` statement rather than the ``print()`` function is often one of the first signs that you're looking at Python 2 code." 414 | ] 415 | }, 416 | { 417 | "cell_type": "markdown", 418 | "metadata": {}, 419 | "source": [ 420 | "## Finishing Up and Learning More\n", 421 | "\n", 422 | "This has been a very brief exploration of the essential features of Python syntax; its purpose is to give you a good frame of reference for when you're reading the code in later sections.\n", 423 | "Several times we've mentioned Python \"style guides\", which can help teams to write code in a consistent style.\n", 424 | "The most widely used style guide in Python is known as PEP8, and can be found at https://www.python.org/dev/peps/pep-0008/.\n", 425 | "As you begin to write more Python code, it would be useful to read through this!\n", 426 | "The style suggestions contain the wisdom of many Python gurus, and most suggestions go beyond simple pedantry: they are experience-based recommendations that can help avoid subtle mistakes and bugs in your code." 427 | ] 428 | }, 429 | { 430 | "cell_type": "markdown", 431 | "metadata": {}, 432 | "source": [ 433 | "\n", 434 | "< [How to Run Python Code](01-How-to-Run-Python-Code.ipynb) | [Contents](Index.ipynb) | [Basic Python Semantics: Variables and Objects](03-Semantics-Variables.ipynb) >" 435 | ] 436 | } 437 | ], 438 | "metadata": { 439 | "anaconda-cloud": {}, 440 | "kernelspec": { 441 | "display_name": "Python 3", 442 | "language": "python", 443 | "name": "python3" 444 | }, 445 | "language_info": { 446 | "codemirror_mode": { 447 | "name": "ipython", 448 | "version": 3 449 | }, 450 | "file_extension": ".py", 451 | "mimetype": "text/x-python", 452 | "name": "python", 453 | "nbconvert_exporter": "python", 454 | "pygments_lexer": "ipython3", 455 | "version": "3.5.1" 456 | } 457 | }, 458 | "nbformat": 4, 459 | "nbformat_minor": 0 460 | } 461 | -------------------------------------------------------------------------------- /03-Semantics-Variables.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "*This notebook contains an excerpt from the [Whirlwind Tour of Python](http://www.oreilly.com/programming/free/a-whirlwind-tour-of-python.csp) by Jake VanderPlas; the content is available [on GitHub](https://github.com/jakevdp/WhirlwindTourOfPython).*\n", 10 | "\n", 11 | "*The text and code are released under the [CC0](https://github.com/jakevdp/WhirlwindTourOfPython/blob/master/LICENSE) license; see also the companion project, the [Python Data Science Handbook](https://github.com/jakevdp/PythonDataScienceHandbook).*\n" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "\n", 19 | "< [A Quick Tour of Python Language Syntax](02-Basic-Python-Syntax.ipynb) | [Contents](Index.ipynb) | [Basic Python Semantics: Operators](04-Semantics-Operators.ipynb) >" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "# Basic Python Semantics: Variables and Objects" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "This section will begin to cover the basic semantics of the Python language.\n", 34 | "As opposed to the *syntax* covered in the previous section, the *semantics* of a language involve the meaning of the statements.\n", 35 | "As with our discussion of syntax, here we'll preview a few of the essential semantic constructions in Python to give you a better frame of reference for understanding the code in the following sections.\n", 36 | "\n", 37 | "This section will cover the semantics of *variables* and *objects*, which are the main ways you store, reference, and operate on data within a Python script." 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "## Python Variables Are Pointers\n", 45 | "\n", 46 | "Assigning variables in Python is as easy as putting a variable name to the left of the equals (``=``) sign:\n", 47 | "\n", 48 | "```python\n", 49 | "# assign 4 to the variable x\n", 50 | "x = 4\n", 51 | "```\n", 52 | "\n", 53 | "This may seem straightforward, but if you have the wrong mental model of what this operation does, the way Python works may seem confusing.\n", 54 | "We'll briefly dig into that here.\n", 55 | "\n", 56 | "In many programming languages, variables are best thought of as containers or buckets into which you put data.\n", 57 | "So in C, for example, when you write\n", 58 | "\n", 59 | "```C\n", 60 | "// C code\n", 61 | "int x = 4;\n", 62 | "```\n", 63 | "\n", 64 | "you are essentially defining a \"memory bucket\" named ``x``, and putting the value ``4`` into it.\n", 65 | "In Python, by contrast, variables are best thought of not as containers but as pointers.\n", 66 | "So in Python, when you write\n", 67 | "\n", 68 | "```python\n", 69 | "x = 4\n", 70 | "```\n", 71 | "\n", 72 | "you are essentially defining a *pointer* named ``x`` that points to some other bucket containing the value ``4``.\n", 73 | "Note one consequence of this: because Python variables just point to various objects, there is no need to \"declare\" the variable, or even require the variable to always point to information of the same type!\n", 74 | "This is the sense in which people say Python is *dynamically-typed*: variable names can point to objects of any type.\n", 75 | "So in Python, you can do things like this:" 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": 1, 81 | "metadata": { 82 | "collapsed": false 83 | }, 84 | "outputs": [], 85 | "source": [ 86 | "x = 1 # x is an integer\n", 87 | "x = 'hello' # now x is a string\n", 88 | "x = [1, 2, 3] # now x is a list" 89 | ] 90 | }, 91 | { 92 | "cell_type": "markdown", 93 | "metadata": {}, 94 | "source": [ 95 | "While users of statically-typed languages might miss the type-safety that comes with declarations like those found in C,\n", 96 | "\n", 97 | "```C\n", 98 | "int x = 4;\n", 99 | "```\n", 100 | "\n", 101 | "this dynamic typing is one of the pieces that makes Python so quick to write and easy to read.\n", 102 | "\n", 103 | "There is a consequence of this \"variable as pointer\" approach that you need to be aware of.\n", 104 | "If we have two variable names pointing to the same *mutable* object, then changing one will change the other as well!\n", 105 | "For example, let's create and modify a list:" 106 | ] 107 | }, 108 | { 109 | "cell_type": "code", 110 | "execution_count": 2, 111 | "metadata": { 112 | "collapsed": false 113 | }, 114 | "outputs": [], 115 | "source": [ 116 | "x = [1, 2, 3]\n", 117 | "y = x" 118 | ] 119 | }, 120 | { 121 | "cell_type": "markdown", 122 | "metadata": {}, 123 | "source": [ 124 | "We've created two variables ``x`` and ``y`` which both point to the same object.\n", 125 | "Because of this, if we modify the list via one of its names, we'll see that the \"other\" list will be modified as well:" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": 3, 131 | "metadata": { 132 | "collapsed": false 133 | }, 134 | "outputs": [ 135 | { 136 | "name": "stdout", 137 | "output_type": "stream", 138 | "text": [ 139 | "[1, 2, 3]\n" 140 | ] 141 | } 142 | ], 143 | "source": [ 144 | "print(y)" 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": 4, 150 | "metadata": { 151 | "collapsed": false 152 | }, 153 | "outputs": [ 154 | { 155 | "name": "stdout", 156 | "output_type": "stream", 157 | "text": [ 158 | "[1, 2, 3, 4]\n" 159 | ] 160 | } 161 | ], 162 | "source": [ 163 | "x.append(4) # append 4 to the list pointed to by x\n", 164 | "print(y) # y's list is modified as well!" 165 | ] 166 | }, 167 | { 168 | "cell_type": "markdown", 169 | "metadata": {}, 170 | "source": [ 171 | "This behavior might seem confusing if you're wrongly thinking of variables as buckets that contain data.\n", 172 | "But if you're correctly thinking of variables as pointers to objects, then this behavior makes sense.\n", 173 | "\n", 174 | "Note also that if we use \"``=``\" to assign another value to ``x``, this will not affect the value of ``y`` – assignment is simply a change of what object the variable points to:" 175 | ] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "execution_count": 5, 180 | "metadata": { 181 | "collapsed": false 182 | }, 183 | "outputs": [ 184 | { 185 | "name": "stdout", 186 | "output_type": "stream", 187 | "text": [ 188 | "[1, 2, 3, 4]\n" 189 | ] 190 | } 191 | ], 192 | "source": [ 193 | "x = 'something else'\n", 194 | "print(y) # y is unchanged" 195 | ] 196 | }, 197 | { 198 | "cell_type": "markdown", 199 | "metadata": {}, 200 | "source": [ 201 | "Again, this makes perfect sense if you think of ``x`` and ``y`` as pointers, and the \"``=``\" operator as an operation that changes what the name points to.\n", 202 | "\n", 203 | "You might wonder whether this pointer idea makes arithmetic operations in Python difficult to track, but Python is set up so that this is not an issue. Numbers, strings, and other *simple types* are immutable: you can't change their value – you can only change what values the variables point to.\n", 204 | "So, for example, it's perfectly safe to do operations like the following:" 205 | ] 206 | }, 207 | { 208 | "cell_type": "code", 209 | "execution_count": 6, 210 | "metadata": { 211 | "collapsed": false 212 | }, 213 | "outputs": [ 214 | { 215 | "name": "stdout", 216 | "output_type": "stream", 217 | "text": [ 218 | "x = 15\n", 219 | "y = 10\n" 220 | ] 221 | } 222 | ], 223 | "source": [ 224 | "x = 10\n", 225 | "y = x\n", 226 | "x += 5 # add 5 to x's value, and assign it to x\n", 227 | "print(\"x =\", x)\n", 228 | "print(\"y =\", y)" 229 | ] 230 | }, 231 | { 232 | "cell_type": "markdown", 233 | "metadata": {}, 234 | "source": [ 235 | "When we call ``x += 5``, we are not modifying the value of the ``10`` object pointed to by ``x``; we are rather changing the variable ``x`` so that it points to a new integer object with value ``15``.\n", 236 | "For this reason, the value of ``y`` is not affected by the operation." 237 | ] 238 | }, 239 | { 240 | "cell_type": "markdown", 241 | "metadata": {}, 242 | "source": [ 243 | "## Everything Is an Object\n", 244 | "\n", 245 | "Python is an object-oriented programming language, and in Python everything is an object.\n", 246 | "\n", 247 | "Let's flesh-out what this means. Earlier we saw that variables are simply pointers, and the variable names themselves have no attached type information.\n", 248 | "This leads some to claim erroneously that Python is a type-free language. But this is not the case!\n", 249 | "Consider the following:" 250 | ] 251 | }, 252 | { 253 | "cell_type": "code", 254 | "execution_count": 7, 255 | "metadata": { 256 | "collapsed": false 257 | }, 258 | "outputs": [ 259 | { 260 | "data": { 261 | "text/plain": [ 262 | "int" 263 | ] 264 | }, 265 | "execution_count": 7, 266 | "metadata": {}, 267 | "output_type": "execute_result" 268 | } 269 | ], 270 | "source": [ 271 | "x = 4\n", 272 | "type(x)" 273 | ] 274 | }, 275 | { 276 | "cell_type": "code", 277 | "execution_count": 8, 278 | "metadata": { 279 | "collapsed": false 280 | }, 281 | "outputs": [ 282 | { 283 | "data": { 284 | "text/plain": [ 285 | "str" 286 | ] 287 | }, 288 | "execution_count": 8, 289 | "metadata": {}, 290 | "output_type": "execute_result" 291 | } 292 | ], 293 | "source": [ 294 | "x = 'hello'\n", 295 | "type(x)" 296 | ] 297 | }, 298 | { 299 | "cell_type": "code", 300 | "execution_count": 9, 301 | "metadata": { 302 | "collapsed": false 303 | }, 304 | "outputs": [ 305 | { 306 | "data": { 307 | "text/plain": [ 308 | "float" 309 | ] 310 | }, 311 | "execution_count": 9, 312 | "metadata": {}, 313 | "output_type": "execute_result" 314 | } 315 | ], 316 | "source": [ 317 | "x = 3.14159\n", 318 | "type(x)" 319 | ] 320 | }, 321 | { 322 | "cell_type": "markdown", 323 | "metadata": {}, 324 | "source": [ 325 | "Python has types; however, the types are linked not to the variable names but *to the objects themselves*.\n", 326 | "\n", 327 | "In object-oriented programming languages like Python, an *object* is an entity that contains data along with associated metadata and/or functionality.\n", 328 | "In Python everything is an object, which means every entity has some metadata (called *attributes*) and associated functionality (called *methods*).\n", 329 | "These attributes and methods are accessed via the dot syntax.\n", 330 | "\n", 331 | "For example, before we saw that lists have an ``append`` method, which adds an item to the list, and is accessed via the dot (\"``.``\") syntax:" 332 | ] 333 | }, 334 | { 335 | "cell_type": "code", 336 | "execution_count": 10, 337 | "metadata": { 338 | "collapsed": false 339 | }, 340 | "outputs": [ 341 | { 342 | "name": "stdout", 343 | "output_type": "stream", 344 | "text": [ 345 | "[1, 2, 3, 100]\n" 346 | ] 347 | } 348 | ], 349 | "source": [ 350 | "L = [1, 2, 3]\n", 351 | "L.append(100)\n", 352 | "print(L)" 353 | ] 354 | }, 355 | { 356 | "cell_type": "markdown", 357 | "metadata": {}, 358 | "source": [ 359 | "While it might be expected for compound objects like lists to have attributes and methods, what is sometimes unexpected is that in Python even simple types have attached attributes and methods.\n", 360 | "For example, numerical types have a ``real`` and ``imag`` attribute that returns the real and imaginary part of the value, if viewed as a complex number:" 361 | ] 362 | }, 363 | { 364 | "cell_type": "code", 365 | "execution_count": 11, 366 | "metadata": { 367 | "collapsed": false 368 | }, 369 | "outputs": [ 370 | { 371 | "name": "stdout", 372 | "output_type": "stream", 373 | "text": [ 374 | "4.5 + 0.0 i\n" 375 | ] 376 | } 377 | ], 378 | "source": [ 379 | "x = 4.5\n", 380 | "print(x.real, \"+\", x.imag, 'i')" 381 | ] 382 | }, 383 | { 384 | "cell_type": "markdown", 385 | "metadata": {}, 386 | "source": [ 387 | "Methods are like attributes, except they are functions that you can call using opening and closing parentheses.\n", 388 | "For example, floating point numbers have a method called ``is_integer`` that checks whether the value is an integer:" 389 | ] 390 | }, 391 | { 392 | "cell_type": "code", 393 | "execution_count": 12, 394 | "metadata": { 395 | "collapsed": false 396 | }, 397 | "outputs": [ 398 | { 399 | "data": { 400 | "text/plain": [ 401 | "False" 402 | ] 403 | }, 404 | "execution_count": 12, 405 | "metadata": {}, 406 | "output_type": "execute_result" 407 | } 408 | ], 409 | "source": [ 410 | "x = 4.5\n", 411 | "x.is_integer()" 412 | ] 413 | }, 414 | { 415 | "cell_type": "code", 416 | "execution_count": 13, 417 | "metadata": { 418 | "collapsed": false 419 | }, 420 | "outputs": [ 421 | { 422 | "data": { 423 | "text/plain": [ 424 | "True" 425 | ] 426 | }, 427 | "execution_count": 13, 428 | "metadata": {}, 429 | "output_type": "execute_result" 430 | } 431 | ], 432 | "source": [ 433 | "x = 4.0\n", 434 | "x.is_integer()" 435 | ] 436 | }, 437 | { 438 | "cell_type": "markdown", 439 | "metadata": {}, 440 | "source": [ 441 | "When we say that everything in Python is an object, we really mean that *everything* is an object – even the attributes and methods of objects are themselves objects with their own ``type`` information:" 442 | ] 443 | }, 444 | { 445 | "cell_type": "code", 446 | "execution_count": 14, 447 | "metadata": { 448 | "collapsed": false 449 | }, 450 | "outputs": [ 451 | { 452 | "data": { 453 | "text/plain": [ 454 | "builtin_function_or_method" 455 | ] 456 | }, 457 | "execution_count": 14, 458 | "metadata": {}, 459 | "output_type": "execute_result" 460 | } 461 | ], 462 | "source": [ 463 | "type(x.is_integer)" 464 | ] 465 | }, 466 | { 467 | "cell_type": "markdown", 468 | "metadata": {}, 469 | "source": [ 470 | "We'll find that the everything-is-object design choice of Python allows for some very convenient language constructs." 471 | ] 472 | }, 473 | { 474 | "cell_type": "markdown", 475 | "metadata": {}, 476 | "source": [ 477 | "\n", 478 | "< [A Quick Tour of Python Language Syntax](02-Basic-Python-Syntax.ipynb) | [Contents](Index.ipynb) | [Basic Python Semantics: Operators](04-Semantics-Operators.ipynb) >" 479 | ] 480 | } 481 | ], 482 | "metadata": { 483 | "anaconda-cloud": {}, 484 | "kernelspec": { 485 | "display_name": "Python 3", 486 | "language": "python", 487 | "name": "python3" 488 | }, 489 | "language_info": { 490 | "codemirror_mode": { 491 | "name": "ipython", 492 | "version": 3 493 | }, 494 | "file_extension": ".py", 495 | "mimetype": "text/x-python", 496 | "name": "python", 497 | "nbconvert_exporter": "python", 498 | "pygments_lexer": "ipython3", 499 | "version": "3.5.1" 500 | } 501 | }, 502 | "nbformat": 4, 503 | "nbformat_minor": 0 504 | } 505 | -------------------------------------------------------------------------------- /07-Control-Flow-Statements.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "*This notebook contains an excerpt from the [Whirlwind Tour of Python](http://www.oreilly.com/programming/free/a-whirlwind-tour-of-python.csp) by Jake VanderPlas; the content is available [on GitHub](https://github.com/jakevdp/WhirlwindTourOfPython).*\n", 10 | "\n", 11 | "*The text and code are released under the [CC0](https://github.com/jakevdp/WhirlwindTourOfPython/blob/master/LICENSE) license; see also the companion project, the [Python Data Science Handbook](https://github.com/jakevdp/PythonDataScienceHandbook).*\n" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "\n", 19 | "< [Built-In Data Structures](06-Built-in-Data-Structures.ipynb) | [Contents](Index.ipynb) | [Defining and Using Functions](08-Defining-Functions.ipynb) >" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "# Control Flow" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "*Control flow* is where the rubber really meets the road in programming.\n", 34 | "Without it, a program is simply a list of statements that are sequentially executed.\n", 35 | "With control flow, you can execute certain code blocks conditionally and/or repeatedly: these basic building blocks can be combined to create surprisingly sophisticated programs!\n", 36 | "\n", 37 | "Here we'll cover *conditional statements* (including \"``if``\", \"``elif``\", and \"``else``\"), *loop statements* (including \"``for``\" and \"``while``\" and the accompanying \"``break``\", \"``continue``\", and \"``pass``\")." 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "## Conditional Statements: ``if``-``elif``-``else``:\n", 45 | "Conditional statements, often referred to as *if-then* statements, allow the programmer to execute certain pieces of code depending on some Boolean condition.\n", 46 | "A basic example of a Python conditional statement is this:" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 1, 52 | "metadata": { 53 | "collapsed": false 54 | }, 55 | "outputs": [ 56 | { 57 | "name": "stdout", 58 | "output_type": "stream", 59 | "text": [ 60 | "-15 is negative\n" 61 | ] 62 | } 63 | ], 64 | "source": [ 65 | "x = -15\n", 66 | "\n", 67 | "if x == 0:\n", 68 | " print(x, \"is zero\")\n", 69 | "elif x > 0:\n", 70 | " print(x, \"is positive\")\n", 71 | "elif x < 0:\n", 72 | " print(x, \"is negative\")\n", 73 | "else:\n", 74 | " print(x, \"is unlike anything I've ever seen...\")" 75 | ] 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "metadata": {}, 80 | "source": [ 81 | "Note especially the use of colons (``:``) and whitespace to denote separate blocks of code.\n", 82 | "\n", 83 | "Python adopts the ``if`` and ``else`` often used in other languages; its more unique keyword is ``elif``, a contraction of \"else if\".\n", 84 | "In these conditional clauses, ``elif`` and ``else`` blocks are optional; additionally, you can optinally include as few or as many ``elif`` statements as you would like." 85 | ] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "metadata": {}, 90 | "source": [ 91 | "## ``for`` loops\n", 92 | "Loops in Python are a way to repeatedly execute some code statement.\n", 93 | "So, for example, if we'd like to print each of the items in a list, we can use a ``for`` loop:" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": 2, 99 | "metadata": { 100 | "collapsed": false 101 | }, 102 | "outputs": [ 103 | { 104 | "name": "stdout", 105 | "output_type": "stream", 106 | "text": [ 107 | "2 3 5 7 " 108 | ] 109 | } 110 | ], 111 | "source": [ 112 | "for N in [2, 3, 5, 7]:\n", 113 | " print(N, end=' ') # print all on same line" 114 | ] 115 | }, 116 | { 117 | "cell_type": "markdown", 118 | "metadata": {}, 119 | "source": [ 120 | "Notice the simplicity of the ``for`` loop: we specify the variable we want to use, the sequence we want to loop over, and use the \"``in``\" operator to link them together in an intuitive and readable way.\n", 121 | "More precisely, the object to the right of the \"``in``\" can be any Python *iterator*.\n", 122 | "An iterator can be thought of as a generalized sequence, and we'll discuss them in [Iterators](10-Iterators.ipynb).\n", 123 | "\n", 124 | "For example, one of the most commonly-used iterators in Python is the ``range`` object, which generates a sequence of numbers:" 125 | ] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "execution_count": 3, 130 | "metadata": { 131 | "collapsed": false 132 | }, 133 | "outputs": [ 134 | { 135 | "name": "stdout", 136 | "output_type": "stream", 137 | "text": [ 138 | "0 1 2 3 4 5 6 7 8 9 " 139 | ] 140 | } 141 | ], 142 | "source": [ 143 | "for i in range(10):\n", 144 | " print(i, end=' ')" 145 | ] 146 | }, 147 | { 148 | "cell_type": "markdown", 149 | "metadata": {}, 150 | "source": [ 151 | "Note that the range starts at zero by default, and that by convention the top of the range is not included in the output.\n", 152 | "Range objects can also have more complicated values:" 153 | ] 154 | }, 155 | { 156 | "cell_type": "code", 157 | "execution_count": 4, 158 | "metadata": { 159 | "collapsed": false 160 | }, 161 | "outputs": [ 162 | { 163 | "data": { 164 | "text/plain": [ 165 | "[5, 6, 7, 8, 9]" 166 | ] 167 | }, 168 | "execution_count": 4, 169 | "metadata": {}, 170 | "output_type": "execute_result" 171 | } 172 | ], 173 | "source": [ 174 | "# range from 5 to 10\n", 175 | "list(range(5, 10))" 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": 5, 181 | "metadata": { 182 | "collapsed": false 183 | }, 184 | "outputs": [ 185 | { 186 | "data": { 187 | "text/plain": [ 188 | "[0, 2, 4, 6, 8]" 189 | ] 190 | }, 191 | "execution_count": 5, 192 | "metadata": {}, 193 | "output_type": "execute_result" 194 | } 195 | ], 196 | "source": [ 197 | "# range from 0 to 10 by 2\n", 198 | "list(range(0, 10, 2))" 199 | ] 200 | }, 201 | { 202 | "cell_type": "markdown", 203 | "metadata": {}, 204 | "source": [ 205 | "You might notice that the meaning of ``range`` arguments is very similar to the slicing syntax that we covered in [Lists](06-Built-in-Data-Structures.ipynb#Lists).\n", 206 | "\n", 207 | "Note that the behavior of ``range()`` is one of the differences between Python 2 and Python 3: in Python 2, ``range()`` produces a list, while in Python 3, ``range()`` produces an iterable object." 208 | ] 209 | }, 210 | { 211 | "cell_type": "markdown", 212 | "metadata": {}, 213 | "source": [ 214 | "## ``while`` loops\n", 215 | "The other type of loop in Python is a ``while`` loop, which iterates until some condition is met:" 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "execution_count": 6, 221 | "metadata": { 222 | "collapsed": false 223 | }, 224 | "outputs": [ 225 | { 226 | "name": "stdout", 227 | "output_type": "stream", 228 | "text": [ 229 | "0 1 2 3 4 5 6 7 8 9 " 230 | ] 231 | } 232 | ], 233 | "source": [ 234 | "i = 0\n", 235 | "while i < 10:\n", 236 | " print(i, end=' ')\n", 237 | " i += 1" 238 | ] 239 | }, 240 | { 241 | "cell_type": "markdown", 242 | "metadata": {}, 243 | "source": [ 244 | "The argument of the ``while`` loop is evaluated as a boolean statement, and the loop is executed until the statement evaluates to False." 245 | ] 246 | }, 247 | { 248 | "cell_type": "markdown", 249 | "metadata": {}, 250 | "source": [ 251 | "## ``break`` and ``continue``: Fine-Tuning Your Loops\n", 252 | "There are two useful statements that can be used within loops to fine-tune how they are executed:\n", 253 | "\n", 254 | "- The ``break`` statement breaks-out of the loop entirely\n", 255 | "- The ``continue`` statement skips the remainder of the current loop, and goes to the next iteration\n", 256 | "\n", 257 | "These can be used in both ``for`` and ``while`` loops.\n", 258 | "\n", 259 | "Here is an example of using ``continue`` to print a string of odd numbers.\n", 260 | "In this case, the result could be accomplished just as well with an ``if-else`` statement, but sometimes the ``continue`` statement can be a more convenient way to express the idea you have in mind:" 261 | ] 262 | }, 263 | { 264 | "cell_type": "code", 265 | "execution_count": 7, 266 | "metadata": { 267 | "collapsed": false 268 | }, 269 | "outputs": [ 270 | { 271 | "name": "stdout", 272 | "output_type": "stream", 273 | "text": [ 274 | "1 3 5 7 9 11 13 15 17 19 " 275 | ] 276 | } 277 | ], 278 | "source": [ 279 | "for n in range(20):\n", 280 | " # if the remainder of n / 2 is 0, skip the rest of the loop\n", 281 | " if n % 2 == 0:\n", 282 | " continue\n", 283 | " print(n, end=' ')" 284 | ] 285 | }, 286 | { 287 | "cell_type": "markdown", 288 | "metadata": {}, 289 | "source": [ 290 | "Here is an example of a ``break`` statement used for a less trivial task.\n", 291 | "This loop will fill a list with all Fibonacci numbers up to a certain value:" 292 | ] 293 | }, 294 | { 295 | "cell_type": "code", 296 | "execution_count": 8, 297 | "metadata": { 298 | "collapsed": false 299 | }, 300 | "outputs": [ 301 | { 302 | "name": "stdout", 303 | "output_type": "stream", 304 | "text": [ 305 | "[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]\n" 306 | ] 307 | } 308 | ], 309 | "source": [ 310 | "a, b = 0, 1\n", 311 | "amax = 100\n", 312 | "L = []\n", 313 | "\n", 314 | "while True:\n", 315 | " (a, b) = (b, a + b)\n", 316 | " if a > amax:\n", 317 | " break\n", 318 | " L.append(a)\n", 319 | "\n", 320 | "print(L)" 321 | ] 322 | }, 323 | { 324 | "cell_type": "markdown", 325 | "metadata": {}, 326 | "source": [ 327 | "Notice that we use a ``while True`` loop, which will loop forever unless we have a break statement!" 328 | ] 329 | }, 330 | { 331 | "cell_type": "markdown", 332 | "metadata": {}, 333 | "source": [ 334 | "## Loops with an ``else`` Block\n", 335 | "One rarely used pattern available in Python is the ``else`` statement as part of a ``for`` or ``while`` loop.\n", 336 | "We discussed the ``else`` block earlier: it executes if all the ``if`` and ``elif`` statements evaluate to ``False``.\n", 337 | "The loop-``else`` is perhaps one of the more confusingly-named statements in Python; I prefer to think of it as a ``nobreak`` statement: that is, the ``else`` block is executed only if the loop ends naturally, without encountering a ``break`` statement.\n", 338 | "\n", 339 | "As an example of where this might be useful, consider the following (non-optimized) implementation of the *Sieve of Eratosthenes*, a well-known algorithm for finding prime numbers:" 340 | ] 341 | }, 342 | { 343 | "cell_type": "code", 344 | "execution_count": 9, 345 | "metadata": { 346 | "collapsed": false 347 | }, 348 | "outputs": [ 349 | { 350 | "name": "stdout", 351 | "output_type": "stream", 352 | "text": [ 353 | "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]\n" 354 | ] 355 | } 356 | ], 357 | "source": [ 358 | "L = []\n", 359 | "nmax = 30\n", 360 | "\n", 361 | "for n in range(2, nmax):\n", 362 | " for factor in L:\n", 363 | " if n % factor == 0:\n", 364 | " break\n", 365 | " else: # no break\n", 366 | " L.append(n)\n", 367 | "print(L)" 368 | ] 369 | }, 370 | { 371 | "cell_type": "markdown", 372 | "metadata": {}, 373 | "source": [ 374 | "The ``else`` statement only executes if none of the factors divide the given number.\n", 375 | "The ``else`` statement works similarly with the ``while`` loop." 376 | ] 377 | }, 378 | { 379 | "cell_type": "markdown", 380 | "metadata": {}, 381 | "source": [ 382 | "\n", 383 | "< [Built-In Data Structures](06-Built-in-Data-Structures.ipynb) | [Contents](Index.ipynb) | [Defining and Using Functions](08-Defining-Functions.ipynb) >" 384 | ] 385 | } 386 | ], 387 | "metadata": { 388 | "anaconda-cloud": {}, 389 | "kernelspec": { 390 | "display_name": "Python 3", 391 | "language": "python", 392 | "name": "python3" 393 | }, 394 | "language_info": { 395 | "codemirror_mode": { 396 | "name": "ipython", 397 | "version": 3 398 | }, 399 | "file_extension": ".py", 400 | "mimetype": "text/x-python", 401 | "name": "python", 402 | "nbconvert_exporter": "python", 403 | "pygments_lexer": "ipython3", 404 | "version": "3.5.1" 405 | } 406 | }, 407 | "nbformat": 4, 408 | "nbformat_minor": 0 409 | } 410 | -------------------------------------------------------------------------------- /08-Defining-Functions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "*This notebook contains an excerpt from the [Whirlwind Tour of Python](http://www.oreilly.com/programming/free/a-whirlwind-tour-of-python.csp) by Jake VanderPlas; the content is available [on GitHub](https://github.com/jakevdp/WhirlwindTourOfPython).*\n", 10 | "\n", 11 | "*The text and code are released under the [CC0](https://github.com/jakevdp/WhirlwindTourOfPython/blob/master/LICENSE) license; see also the companion project, the [Python Data Science Handbook](https://github.com/jakevdp/PythonDataScienceHandbook).*\n" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "\n", 19 | "< [Control Flow](07-Control-Flow-Statements.ipynb) | [Contents](Index.ipynb) | [Errors and Exceptions](09-Errors-and-Exceptions.ipynb) >" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "# Defining and Using Functions" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "So far, our scripts have been simple, single-use code blocks.\n", 34 | "One way to organize our Python code and to make it more readable and reusable is to factor-out useful pieces into reusable *functions*.\n", 35 | "Here we'll cover two ways of creating functions: the ``def`` statement, useful for any type of function, and the ``lambda`` statement, useful for creating short anonymous functions." 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "## Using Functions\n", 43 | "\n", 44 | "Functions are groups of code that have a name, and can be called using parentheses.\n", 45 | "We've seen functions before. For example, ``print`` in Python 3 is a function:" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": 1, 51 | "metadata": { 52 | "collapsed": false 53 | }, 54 | "outputs": [ 55 | { 56 | "name": "stdout", 57 | "output_type": "stream", 58 | "text": [ 59 | "abc\n" 60 | ] 61 | } 62 | ], 63 | "source": [ 64 | "print('abc')" 65 | ] 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "metadata": {}, 70 | "source": [ 71 | "Here ``print`` is the function name, and ``'abc'`` is the function's *argument*.\n", 72 | "\n", 73 | "In addition to arguments, there are *keyword arguments* that are specified by name.\n", 74 | "One available keyword argument for the ``print()`` function (in Python 3) is ``sep``, which tells what character or characters should be used to separate multiple items:" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": 2, 80 | "metadata": { 81 | "collapsed": false 82 | }, 83 | "outputs": [ 84 | { 85 | "name": "stdout", 86 | "output_type": "stream", 87 | "text": [ 88 | "1 2 3\n" 89 | ] 90 | } 91 | ], 92 | "source": [ 93 | "print(1, 2, 3)" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": 3, 99 | "metadata": { 100 | "collapsed": false 101 | }, 102 | "outputs": [ 103 | { 104 | "name": "stdout", 105 | "output_type": "stream", 106 | "text": [ 107 | "1--2--3\n" 108 | ] 109 | } 110 | ], 111 | "source": [ 112 | "print(1, 2, 3, sep='--')" 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": {}, 118 | "source": [ 119 | "When non-keyword arguments are used together with keyword arguments, the keyword arguments must come at the end." 120 | ] 121 | }, 122 | { 123 | "cell_type": "markdown", 124 | "metadata": {}, 125 | "source": [ 126 | "## Defining Functions\n", 127 | "Functions become even more useful when we begin to define our own, organizing functionality to be used in multiple places.\n", 128 | "In Python, functions are defined with the ``def`` statement.\n", 129 | "For example, we can encapsulate a version of our Fibonacci sequence code from the previous section as follows:" 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": 4, 135 | "metadata": { 136 | "collapsed": false 137 | }, 138 | "outputs": [], 139 | "source": [ 140 | "def fibonacci(N):\n", 141 | " L = []\n", 142 | " a, b = 0, 1\n", 143 | " while len(L) < N:\n", 144 | " a, b = b, a + b\n", 145 | " L.append(a)\n", 146 | " return L" 147 | ] 148 | }, 149 | { 150 | "cell_type": "markdown", 151 | "metadata": {}, 152 | "source": [ 153 | "Now we have a function named ``fibonacci`` which takes a single argument ``N``, does something with this argument, and ``return``s a value; in this case, a list of the first ``N`` Fibonacci numbers:" 154 | ] 155 | }, 156 | { 157 | "cell_type": "code", 158 | "execution_count": 5, 159 | "metadata": { 160 | "collapsed": false 161 | }, 162 | "outputs": [ 163 | { 164 | "data": { 165 | "text/plain": [ 166 | "[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]" 167 | ] 168 | }, 169 | "execution_count": 5, 170 | "metadata": {}, 171 | "output_type": "execute_result" 172 | } 173 | ], 174 | "source": [ 175 | "fibonacci(10)" 176 | ] 177 | }, 178 | { 179 | "cell_type": "markdown", 180 | "metadata": {}, 181 | "source": [ 182 | "If you're familiar with strongly-typed languages like ``C``, you'll immediately notice that there is no type information associated with the function inputs or outputs.\n", 183 | "Python functions can return any Python object, simple or compound, which means constructs that may be difficult in other languages are straightforward in Python.\n", 184 | "\n", 185 | "For example, multiple return values are simply put in a tuple, which is indicated by commas:" 186 | ] 187 | }, 188 | { 189 | "cell_type": "code", 190 | "execution_count": 6, 191 | "metadata": { 192 | "collapsed": false 193 | }, 194 | "outputs": [ 195 | { 196 | "name": "stdout", 197 | "output_type": "stream", 198 | "text": [ 199 | "3.0 4.0 (3-4j)\n" 200 | ] 201 | } 202 | ], 203 | "source": [ 204 | "def real_imag_conj(val):\n", 205 | " return val.real, val.imag, val.conjugate()\n", 206 | "\n", 207 | "r, i, c = real_imag_conj(3 + 4j)\n", 208 | "print(r, i, c)" 209 | ] 210 | }, 211 | { 212 | "cell_type": "markdown", 213 | "metadata": {}, 214 | "source": [ 215 | "## Default Argument Values\n", 216 | "\n", 217 | "Often when defining a function, there are certain values that we want the function to use *most* of the time, but we'd also like to give the user some flexibility.\n", 218 | "In this case, we can use *default values* for arguments.\n", 219 | "Consider the ``fibonacci`` function from before.\n", 220 | "What if we would like the user to be able to play with the starting values?\n", 221 | "We could do that as follows:" 222 | ] 223 | }, 224 | { 225 | "cell_type": "code", 226 | "execution_count": 7, 227 | "metadata": { 228 | "collapsed": false 229 | }, 230 | "outputs": [], 231 | "source": [ 232 | "def fibonacci(N, a=0, b=1):\n", 233 | " L = []\n", 234 | " while len(L) < N:\n", 235 | " a, b = b, a + b\n", 236 | " L.append(a)\n", 237 | " return L" 238 | ] 239 | }, 240 | { 241 | "cell_type": "markdown", 242 | "metadata": {}, 243 | "source": [ 244 | "With a single argument, the result of the function call is identical to before:" 245 | ] 246 | }, 247 | { 248 | "cell_type": "code", 249 | "execution_count": 8, 250 | "metadata": { 251 | "collapsed": false 252 | }, 253 | "outputs": [ 254 | { 255 | "data": { 256 | "text/plain": [ 257 | "[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]" 258 | ] 259 | }, 260 | "execution_count": 8, 261 | "metadata": {}, 262 | "output_type": "execute_result" 263 | } 264 | ], 265 | "source": [ 266 | "fibonacci(10)" 267 | ] 268 | }, 269 | { 270 | "cell_type": "markdown", 271 | "metadata": {}, 272 | "source": [ 273 | "But now we can use the function to explore new things, such as the effect of new starting values:" 274 | ] 275 | }, 276 | { 277 | "cell_type": "code", 278 | "execution_count": 9, 279 | "metadata": { 280 | "collapsed": false 281 | }, 282 | "outputs": [ 283 | { 284 | "data": { 285 | "text/plain": [ 286 | "[2, 2, 4, 6, 10, 16, 26, 42, 68, 110]" 287 | ] 288 | }, 289 | "execution_count": 9, 290 | "metadata": {}, 291 | "output_type": "execute_result" 292 | } 293 | ], 294 | "source": [ 295 | "fibonacci(10, 0, 2)" 296 | ] 297 | }, 298 | { 299 | "cell_type": "markdown", 300 | "metadata": {}, 301 | "source": [ 302 | "The values can also be specified by name if desired, in which case the order of the named values does not matter:" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": 10, 308 | "metadata": { 309 | "collapsed": false 310 | }, 311 | "outputs": [ 312 | { 313 | "data": { 314 | "text/plain": [ 315 | "[3, 4, 7, 11, 18, 29, 47, 76, 123, 199]" 316 | ] 317 | }, 318 | "execution_count": 10, 319 | "metadata": {}, 320 | "output_type": "execute_result" 321 | } 322 | ], 323 | "source": [ 324 | "fibonacci(10, b=3, a=1)" 325 | ] 326 | }, 327 | { 328 | "cell_type": "markdown", 329 | "metadata": {}, 330 | "source": [ 331 | "## ``*args`` and ``**kwargs``: Flexible Arguments\n", 332 | "Sometimes you might wish to write a function in which you don't initially know how many arguments the user will pass.\n", 333 | "In this case, you can use the special form ``*args`` and ``**kwargs`` to catch all arguments that are passed.\n", 334 | "Here is an example:" 335 | ] 336 | }, 337 | { 338 | "cell_type": "code", 339 | "execution_count": 11, 340 | "metadata": { 341 | "collapsed": false 342 | }, 343 | "outputs": [], 344 | "source": [ 345 | "def catch_all(*args, **kwargs):\n", 346 | " print(\"args =\", args)\n", 347 | " print(\"kwargs = \", kwargs)" 348 | ] 349 | }, 350 | { 351 | "cell_type": "code", 352 | "execution_count": 12, 353 | "metadata": { 354 | "collapsed": false 355 | }, 356 | "outputs": [ 357 | { 358 | "name": "stdout", 359 | "output_type": "stream", 360 | "text": [ 361 | "args = (1, 2, 3)\n", 362 | "kwargs = {'a': 4, 'b': 5}\n" 363 | ] 364 | } 365 | ], 366 | "source": [ 367 | "catch_all(1, 2, 3, a=4, b=5)" 368 | ] 369 | }, 370 | { 371 | "cell_type": "code", 372 | "execution_count": 13, 373 | "metadata": { 374 | "collapsed": false 375 | }, 376 | "outputs": [ 377 | { 378 | "name": "stdout", 379 | "output_type": "stream", 380 | "text": [ 381 | "args = ('a',)\n", 382 | "kwargs = {'keyword': 2}\n" 383 | ] 384 | } 385 | ], 386 | "source": [ 387 | "catch_all('a', keyword=2)" 388 | ] 389 | }, 390 | { 391 | "cell_type": "markdown", 392 | "metadata": {}, 393 | "source": [ 394 | "Here it is not the names ``args`` and ``kwargs`` that are important, but the ``*`` characters preceding them.\n", 395 | "``args`` and ``kwargs`` are just the variable names often used by convention, short for \"arguments\" and \"keyword arguments\".\n", 396 | "The operative difference is the asterisk characters: a single ``*`` before a variable means \"expand this as a sequence\", while a double ``**`` before a variable means \"expand this as a dictionary\".\n", 397 | "In fact, this syntax can be used not only with the function definition, but with the function call as well!" 398 | ] 399 | }, 400 | { 401 | "cell_type": "code", 402 | "execution_count": 14, 403 | "metadata": { 404 | "collapsed": false 405 | }, 406 | "outputs": [ 407 | { 408 | "name": "stdout", 409 | "output_type": "stream", 410 | "text": [ 411 | "args = (1, 2, 3)\n", 412 | "kwargs = {'pi': 3.14}\n" 413 | ] 414 | } 415 | ], 416 | "source": [ 417 | "inputs = (1, 2, 3)\n", 418 | "keywords = {'pi': 3.14}\n", 419 | "\n", 420 | "catch_all(*inputs, **keywords)" 421 | ] 422 | }, 423 | { 424 | "cell_type": "markdown", 425 | "metadata": {}, 426 | "source": [ 427 | "## Anonymous (``lambda``) Functions\n", 428 | "Earlier we quickly covered the most common way of defining functions, the ``def`` statement.\n", 429 | "You'll likely come across another way of defining short, one-off functions with the ``lambda`` statement.\n", 430 | "It looks something like this:" 431 | ] 432 | }, 433 | { 434 | "cell_type": "code", 435 | "execution_count": 15, 436 | "metadata": { 437 | "collapsed": false 438 | }, 439 | "outputs": [ 440 | { 441 | "data": { 442 | "text/plain": [ 443 | "3" 444 | ] 445 | }, 446 | "execution_count": 15, 447 | "metadata": {}, 448 | "output_type": "execute_result" 449 | } 450 | ], 451 | "source": [ 452 | "add = lambda x, y: x + y\n", 453 | "add(1, 2)" 454 | ] 455 | }, 456 | { 457 | "cell_type": "markdown", 458 | "metadata": {}, 459 | "source": [ 460 | "This lambda function is roughly equivalent to" 461 | ] 462 | }, 463 | { 464 | "cell_type": "code", 465 | "execution_count": 16, 466 | "metadata": { 467 | "collapsed": false 468 | }, 469 | "outputs": [], 470 | "source": [ 471 | "def add(x, y):\n", 472 | " return x + y" 473 | ] 474 | }, 475 | { 476 | "cell_type": "markdown", 477 | "metadata": {}, 478 | "source": [ 479 | "So why would you ever want to use such a thing?\n", 480 | "Primarily, it comes down to the fact that *everything is an object* in Python, even functions themselves!\n", 481 | "That means that functions can be passed as arguments to functions.\n", 482 | "\n", 483 | "As an example of this, suppose we have some data stored in a list of dictionaries:" 484 | ] 485 | }, 486 | { 487 | "cell_type": "code", 488 | "execution_count": 17, 489 | "metadata": { 490 | "collapsed": false 491 | }, 492 | "outputs": [], 493 | "source": [ 494 | "data = [{'first':'Guido', 'last':'Van Rossum', 'YOB':1956},\n", 495 | " {'first':'Grace', 'last':'Hopper', 'YOB':1906},\n", 496 | " {'first':'Alan', 'last':'Turing', 'YOB':1912}]" 497 | ] 498 | }, 499 | { 500 | "cell_type": "markdown", 501 | "metadata": {}, 502 | "source": [ 503 | "Now suppose we want to sort this data.\n", 504 | "Python has a ``sorted`` function that does this:" 505 | ] 506 | }, 507 | { 508 | "cell_type": "code", 509 | "execution_count": 18, 510 | "metadata": { 511 | "collapsed": false 512 | }, 513 | "outputs": [ 514 | { 515 | "data": { 516 | "text/plain": [ 517 | "[1, 2, 3, 4, 5, 6]" 518 | ] 519 | }, 520 | "execution_count": 18, 521 | "metadata": {}, 522 | "output_type": "execute_result" 523 | } 524 | ], 525 | "source": [ 526 | "sorted([2,4,3,5,1,6])" 527 | ] 528 | }, 529 | { 530 | "cell_type": "markdown", 531 | "metadata": {}, 532 | "source": [ 533 | "But dictionaries are not orderable: we need a way to tell the function *how* to sort our data.\n", 534 | "We can do this by specifying the ``key`` function, a function which given an item returns the sorting key for that item:" 535 | ] 536 | }, 537 | { 538 | "cell_type": "code", 539 | "execution_count": 19, 540 | "metadata": { 541 | "collapsed": false 542 | }, 543 | "outputs": [ 544 | { 545 | "data": { 546 | "text/plain": [ 547 | "[{'YOB': 1912, 'first': 'Alan', 'last': 'Turing'},\n", 548 | " {'YOB': 1906, 'first': 'Grace', 'last': 'Hopper'},\n", 549 | " {'YOB': 1956, 'first': 'Guido', 'last': 'Van Rossum'}]" 550 | ] 551 | }, 552 | "execution_count": 19, 553 | "metadata": {}, 554 | "output_type": "execute_result" 555 | } 556 | ], 557 | "source": [ 558 | "# sort alphabetically by first name\n", 559 | "sorted(data, key=lambda item: item['first'])" 560 | ] 561 | }, 562 | { 563 | "cell_type": "code", 564 | "execution_count": 20, 565 | "metadata": { 566 | "collapsed": false 567 | }, 568 | "outputs": [ 569 | { 570 | "data": { 571 | "text/plain": [ 572 | "[{'YOB': 1906, 'first': 'Grace', 'last': 'Hopper'},\n", 573 | " {'YOB': 1912, 'first': 'Alan', 'last': 'Turing'},\n", 574 | " {'YOB': 1956, 'first': 'Guido', 'last': 'Van Rossum'}]" 575 | ] 576 | }, 577 | "execution_count": 20, 578 | "metadata": {}, 579 | "output_type": "execute_result" 580 | } 581 | ], 582 | "source": [ 583 | "# sort by year of birth\n", 584 | "sorted(data, key=lambda item: item['YOB'])" 585 | ] 586 | }, 587 | { 588 | "cell_type": "markdown", 589 | "metadata": {}, 590 | "source": [ 591 | "While these key functions could certainly be created by the normal, ``def`` syntax, the ``lambda`` syntax is convenient for such short one-off functions like these." 592 | ] 593 | }, 594 | { 595 | "cell_type": "markdown", 596 | "metadata": {}, 597 | "source": [ 598 | "\n", 599 | "< [Control Flow](07-Control-Flow-Statements.ipynb) | [Contents](Index.ipynb) | [Errors and Exceptions](09-Errors-and-Exceptions.ipynb) >" 600 | ] 601 | } 602 | ], 603 | "metadata": { 604 | "anaconda-cloud": {}, 605 | "kernelspec": { 606 | "display_name": "Python 3", 607 | "language": "python", 608 | "name": "python3" 609 | }, 610 | "language_info": { 611 | "codemirror_mode": { 612 | "name": "ipython", 613 | "version": 3 614 | }, 615 | "file_extension": ".py", 616 | "mimetype": "text/x-python", 617 | "name": "python", 618 | "nbconvert_exporter": "python", 619 | "pygments_lexer": "ipython3", 620 | "version": "3.5.1" 621 | } 622 | }, 623 | "nbformat": 4, 624 | "nbformat_minor": 0 625 | } 626 | -------------------------------------------------------------------------------- /11-List-Comprehensions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "*This notebook contains an excerpt from the [Whirlwind Tour of Python](http://www.oreilly.com/programming/free/a-whirlwind-tour-of-python.csp) by Jake VanderPlas; the content is available [on GitHub](https://github.com/jakevdp/WhirlwindTourOfPython).*\n", 10 | "\n", 11 | "*The text and code are released under the [CC0](https://github.com/jakevdp/WhirlwindTourOfPython/blob/master/LICENSE) license; see also the companion project, the [Python Data Science Handbook](https://github.com/jakevdp/PythonDataScienceHandbook).*\n" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "\n", 19 | "< [Iterators](10-Iterators.ipynb) | [Contents](Index.ipynb) | [Generators](12-Generators.ipynb) >" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "# List Comprehensions" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "If you read enough Python code, you'll eventually come across the terse and efficient construction known as a *list comprehension*.\n", 34 | "This is one feature of Python I expect you will fall in love with if you've not used it before; it looks something like this:" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": 1, 40 | "metadata": { 41 | "collapsed": false 42 | }, 43 | "outputs": [ 44 | { 45 | "data": { 46 | "text/plain": [ 47 | "[1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19]" 48 | ] 49 | }, 50 | "execution_count": 1, 51 | "metadata": {}, 52 | "output_type": "execute_result" 53 | } 54 | ], 55 | "source": [ 56 | "[i for i in range(20) if i % 3 > 0]" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "The result of this is a list of numbers which excludes multiples of 3.\n", 64 | "While this example may seem a bit confusing at first, as familiarity with Python grows, reading and writing list comprehensions will become second nature." 65 | ] 66 | }, 67 | { 68 | "cell_type": "markdown", 69 | "metadata": {}, 70 | "source": [ 71 | "## Basic List Comprehensions\n", 72 | "List comprehensions are simply a way to compress a list-building for-loop into a single short, readable line.\n", 73 | "For example, here is a loop that constructs a list of the first 12 square integers:" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": 2, 79 | "metadata": { 80 | "collapsed": false 81 | }, 82 | "outputs": [ 83 | { 84 | "data": { 85 | "text/plain": [ 86 | "[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121]" 87 | ] 88 | }, 89 | "execution_count": 2, 90 | "metadata": {}, 91 | "output_type": "execute_result" 92 | } 93 | ], 94 | "source": [ 95 | "L = []\n", 96 | "for n in range(12):\n", 97 | " L.append(n ** 2)\n", 98 | "L" 99 | ] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": {}, 104 | "source": [ 105 | "The list comprehension equivalent of this is the following:" 106 | ] 107 | }, 108 | { 109 | "cell_type": "code", 110 | "execution_count": 3, 111 | "metadata": { 112 | "collapsed": false 113 | }, 114 | "outputs": [ 115 | { 116 | "data": { 117 | "text/plain": [ 118 | "[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121]" 119 | ] 120 | }, 121 | "execution_count": 3, 122 | "metadata": {}, 123 | "output_type": "execute_result" 124 | } 125 | ], 126 | "source": [ 127 | "[n ** 2 for n in range(12)]" 128 | ] 129 | }, 130 | { 131 | "cell_type": "markdown", 132 | "metadata": {}, 133 | "source": [ 134 | "As with many Python statements, you can almost read-off the meaning of this statement in plain English: \"construct a list consisting of the square of ``n`` for each ``n`` up to 12\".\n", 135 | "\n", 136 | "This basic syntax, then, is ``[``*``expr``* ``for`` *``var``* ``in`` *``iterable``*``]``, where *``expr``* is any valid expression, *``var``* is a variable name, and *``iterable``* is any iterable Python object." 137 | ] 138 | }, 139 | { 140 | "cell_type": "markdown", 141 | "metadata": {}, 142 | "source": [ 143 | "## Multiple Iteration\n", 144 | "Sometimes you want to build a list not just from one value, but from two. To do this, simply add another ``for`` expression in the comprehension:" 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": 4, 150 | "metadata": { 151 | "collapsed": false 152 | }, 153 | "outputs": [ 154 | { 155 | "data": { 156 | "text/plain": [ 157 | "[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]" 158 | ] 159 | }, 160 | "execution_count": 4, 161 | "metadata": {}, 162 | "output_type": "execute_result" 163 | } 164 | ], 165 | "source": [ 166 | "[(i, j) for i in range(2) for j in range(3)]" 167 | ] 168 | }, 169 | { 170 | "cell_type": "markdown", 171 | "metadata": {}, 172 | "source": [ 173 | "Notice that the second ``for`` expression acts as the interior index, varying the fastest in the resulting list.\n", 174 | "This type of construction can be extended to three, four, or more iterators within the comprehension, though at some point code readibility will suffer!" 175 | ] 176 | }, 177 | { 178 | "cell_type": "markdown", 179 | "metadata": {}, 180 | "source": [ 181 | "## Conditionals on the Iterator\n", 182 | "You can further control the iteration by adding a conditional to the end of the expression.\n", 183 | "In the first example of the section, we iterated over all numbers from 1 to 20, but left-out multiples of 3.\n", 184 | "Look at this again, and notice the construction:" 185 | ] 186 | }, 187 | { 188 | "cell_type": "code", 189 | "execution_count": 5, 190 | "metadata": { 191 | "collapsed": false 192 | }, 193 | "outputs": [ 194 | { 195 | "data": { 196 | "text/plain": [ 197 | "[1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19]" 198 | ] 199 | }, 200 | "execution_count": 5, 201 | "metadata": {}, 202 | "output_type": "execute_result" 203 | } 204 | ], 205 | "source": [ 206 | "[val for val in range(20) if val % 3 > 0]" 207 | ] 208 | }, 209 | { 210 | "cell_type": "markdown", 211 | "metadata": {}, 212 | "source": [ 213 | "The expression ``(i % 3 > 0)`` evaluates to ``True`` unless ``val`` is divisible by 3.\n", 214 | "Again, the English language meaning can be immediately read off: \"Construct a list of values for each value up to 20, but only if the value is not divisible by 3\".\n", 215 | "Once you are comfortable with it, this is much easier to write – and to understand at a glance – than the equivalent loop syntax:" 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "execution_count": 6, 221 | "metadata": { 222 | "collapsed": false 223 | }, 224 | "outputs": [ 225 | { 226 | "data": { 227 | "text/plain": [ 228 | "[1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19]" 229 | ] 230 | }, 231 | "execution_count": 6, 232 | "metadata": {}, 233 | "output_type": "execute_result" 234 | } 235 | ], 236 | "source": [ 237 | "L = []\n", 238 | "for val in range(20):\n", 239 | " if val % 3:\n", 240 | " L.append(val)\n", 241 | "L" 242 | ] 243 | }, 244 | { 245 | "cell_type": "markdown", 246 | "metadata": {}, 247 | "source": [ 248 | "## Conditionals on the Value\n", 249 | "If you've programmed in C, you might be familiar with the single-line conditional enabled by the ``?`` operator:\n", 250 | "``` C\n", 251 | "int absval = (val < 0) ? -val : val\n", 252 | "```\n", 253 | "Python has something very similar to this, which is most often used within list comprehensions, ``lambda`` functions, and other places where a simple expression is desired:" 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": 7, 259 | "metadata": { 260 | "collapsed": false 261 | }, 262 | "outputs": [ 263 | { 264 | "data": { 265 | "text/plain": [ 266 | "10" 267 | ] 268 | }, 269 | "execution_count": 7, 270 | "metadata": {}, 271 | "output_type": "execute_result" 272 | } 273 | ], 274 | "source": [ 275 | "val = -10\n", 276 | "val if val >= 0 else -val" 277 | ] 278 | }, 279 | { 280 | "cell_type": "markdown", 281 | "metadata": {}, 282 | "source": [ 283 | "We see that this simply duplicates the functionality of the built-in ``abs()`` function, but the construction lets you do some really interesting things within list comprehensions.\n", 284 | "This is getting pretty complicated now, but you could do something like this:" 285 | ] 286 | }, 287 | { 288 | "cell_type": "code", 289 | "execution_count": 8, 290 | "metadata": { 291 | "collapsed": false 292 | }, 293 | "outputs": [ 294 | { 295 | "data": { 296 | "text/plain": [ 297 | "[1, -2, -4, 5, 7, -8, -10, 11, 13, -14, -16, 17, 19]" 298 | ] 299 | }, 300 | "execution_count": 8, 301 | "metadata": {}, 302 | "output_type": "execute_result" 303 | } 304 | ], 305 | "source": [ 306 | "[val if val % 2 else -val\n", 307 | " for val in range(20) if val % 3]" 308 | ] 309 | }, 310 | { 311 | "cell_type": "markdown", 312 | "metadata": {}, 313 | "source": [ 314 | "Note the line break within the list comprehension before the ``for`` expression: this is valid in Python, and is often a nice way to break-up long list comprehensions for greater readibility.\n", 315 | "Look this over: what we're doing is constructing a list, leaving out multiples of 3, and negating all mutliples of 2." 316 | ] 317 | }, 318 | { 319 | "cell_type": "markdown", 320 | "metadata": {}, 321 | "source": [ 322 | "Once you understand the dynamics of list comprehensions, it's straightforward to move on to other types of comprehensions. The syntax is largely the same; the only difference is the type of bracket you use.\n", 323 | "\n", 324 | "For example, with curly braces you can create a ``set`` with a *set comprehension*:" 325 | ] 326 | }, 327 | { 328 | "cell_type": "code", 329 | "execution_count": 11, 330 | "metadata": { 331 | "collapsed": false 332 | }, 333 | "outputs": [ 334 | { 335 | "data": { 336 | "text/plain": [ 337 | "{0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121}" 338 | ] 339 | }, 340 | "execution_count": 11, 341 | "metadata": {}, 342 | "output_type": "execute_result" 343 | } 344 | ], 345 | "source": [ 346 | "{n**2 for n in range(12)}" 347 | ] 348 | }, 349 | { 350 | "cell_type": "markdown", 351 | "metadata": {}, 352 | "source": [ 353 | "Recall that a ``set`` is a collection that contains no duplicates.\n", 354 | "The set comprehension respects this rule, and eliminates any duplicate entries:" 355 | ] 356 | }, 357 | { 358 | "cell_type": "code", 359 | "execution_count": 12, 360 | "metadata": { 361 | "collapsed": false 362 | }, 363 | "outputs": [ 364 | { 365 | "data": { 366 | "text/plain": [ 367 | "{0, 1, 2}" 368 | ] 369 | }, 370 | "execution_count": 12, 371 | "metadata": {}, 372 | "output_type": "execute_result" 373 | } 374 | ], 375 | "source": [ 376 | "{a % 3 for a in range(1000)}" 377 | ] 378 | }, 379 | { 380 | "cell_type": "markdown", 381 | "metadata": {}, 382 | "source": [ 383 | "With a slight tweak, you can add a colon (``:``) to create a *dict comprehension*:" 384 | ] 385 | }, 386 | { 387 | "cell_type": "code", 388 | "execution_count": 13, 389 | "metadata": { 390 | "collapsed": false 391 | }, 392 | "outputs": [ 393 | { 394 | "data": { 395 | "text/plain": [ 396 | "{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}" 397 | ] 398 | }, 399 | "execution_count": 13, 400 | "metadata": {}, 401 | "output_type": "execute_result" 402 | } 403 | ], 404 | "source": [ 405 | "{n:n**2 for n in range(6)}" 406 | ] 407 | }, 408 | { 409 | "cell_type": "markdown", 410 | "metadata": {}, 411 | "source": [ 412 | "Finally, if you use parentheses rather than square brackets, you get what's called a *generator expression*:" 413 | ] 414 | }, 415 | { 416 | "cell_type": "code", 417 | "execution_count": 15, 418 | "metadata": { 419 | "collapsed": false 420 | }, 421 | "outputs": [ 422 | { 423 | "data": { 424 | "text/plain": [ 425 | " at 0x1027a5a50>" 426 | ] 427 | }, 428 | "execution_count": 15, 429 | "metadata": {}, 430 | "output_type": "execute_result" 431 | } 432 | ], 433 | "source": [ 434 | "(n**2 for n in range(12))" 435 | ] 436 | }, 437 | { 438 | "cell_type": "markdown", 439 | "metadata": {}, 440 | "source": [ 441 | "A generator expression is essentially a list comprehension in which elements are generated as-needed rather than all at-once, and the simplicity here belies the power of this language feature: we'll explore this more next." 442 | ] 443 | }, 444 | { 445 | "cell_type": "markdown", 446 | "metadata": {}, 447 | "source": [ 448 | " " 449 | ] 450 | }, 451 | { 452 | "cell_type": "markdown", 453 | "metadata": {}, 454 | "source": [ 455 | "\n", 456 | "< [Iterators](10-Iterators.ipynb) | [Contents](Index.ipynb) | [Generators](12-Generators.ipynb) >" 457 | ] 458 | } 459 | ], 460 | "metadata": { 461 | "anaconda-cloud": {}, 462 | "kernelspec": { 463 | "display_name": "Python 3", 464 | "language": "python", 465 | "name": "python3" 466 | }, 467 | "language_info": { 468 | "codemirror_mode": { 469 | "name": "ipython", 470 | "version": 3 471 | }, 472 | "file_extension": ".py", 473 | "mimetype": "text/x-python", 474 | "name": "python", 475 | "nbconvert_exporter": "python", 476 | "pygments_lexer": "ipython3", 477 | "version": "3.5.1" 478 | } 479 | }, 480 | "nbformat": 4, 481 | "nbformat_minor": 0 482 | } 483 | -------------------------------------------------------------------------------- /13-Modules-and-Packages.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "*This notebook contains an excerpt from the [Whirlwind Tour of Python](http://www.oreilly.com/programming/free/a-whirlwind-tour-of-python.csp) by Jake VanderPlas; the content is available [on GitHub](https://github.com/jakevdp/WhirlwindTourOfPython).*\n", 10 | "\n", 11 | "*The text and code are released under the [CC0](https://github.com/jakevdp/WhirlwindTourOfPython/blob/master/LICENSE) license; see also the companion project, the [Python Data Science Handbook](https://github.com/jakevdp/PythonDataScienceHandbook).*\n" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "\n", 19 | "< [Generators](12-Generators.ipynb) | [Contents](Index.ipynb) | [String Manipulation and Regular Expressions](14-Strings-and-Regular-Expressions.ipynb) >" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "# Modules and Packages" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "One feature of Python that makes it useful for a wide range of tasks is the fact that it comes \"batteries included\" – that is, the Python standard library contains useful tools for a wide range of tasks.\n", 34 | "On top of this, there is a broad ecosystem of third-party tools and packages that offer more specialized functionality.\n", 35 | "Here we'll take a look at importing standard library modules, tools for installing third-party modules, and a description of how you can make your own modules." 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "## Loading Modules: the ``import`` Statement\n", 43 | "\n", 44 | "For loading built-in and third-party modules, Python provides the ``import`` statement.\n", 45 | "There are a few ways to use the statement, which we will mention briefly here, from most recommended to least recommended." 46 | ] 47 | }, 48 | { 49 | "cell_type": "markdown", 50 | "metadata": {}, 51 | "source": [ 52 | "### Explicit module import\n", 53 | "\n", 54 | "Explicit import of a module preserves the module's content in a namespace.\n", 55 | "The namespace is then used to refer to its contents with a \"``.``\" between them.\n", 56 | "For example, here we'll import the built-in ``math`` module and compute the cosine of pi:" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": 1, 62 | "metadata": { 63 | "collapsed": false 64 | }, 65 | "outputs": [ 66 | { 67 | "data": { 68 | "text/plain": [ 69 | "-1.0" 70 | ] 71 | }, 72 | "execution_count": 1, 73 | "metadata": {}, 74 | "output_type": "execute_result" 75 | } 76 | ], 77 | "source": [ 78 | "import math\n", 79 | "math.cos(math.pi)" 80 | ] 81 | }, 82 | { 83 | "cell_type": "markdown", 84 | "metadata": {}, 85 | "source": [ 86 | "### Explicit module import by alias\n", 87 | "\n", 88 | "For longer module names, it's not convenient to use the full module name each time you access some element.\n", 89 | "For this reason, we'll commonly use the \"``import ... as ...``\" pattern to create a shorter alias for the namespace.\n", 90 | "For example, the NumPy (Numerical Python) package, a popular third-party package useful for data science, is by convention imported under the alias ``np``:" 91 | ] 92 | }, 93 | { 94 | "cell_type": "code", 95 | "execution_count": 2, 96 | "metadata": { 97 | "collapsed": false 98 | }, 99 | "outputs": [ 100 | { 101 | "data": { 102 | "text/plain": [ 103 | "-1.0" 104 | ] 105 | }, 106 | "execution_count": 2, 107 | "metadata": {}, 108 | "output_type": "execute_result" 109 | } 110 | ], 111 | "source": [ 112 | "import numpy as np\n", 113 | "np.cos(np.pi)" 114 | ] 115 | }, 116 | { 117 | "cell_type": "markdown", 118 | "metadata": {}, 119 | "source": [ 120 | "### Explicit import of module contents\n", 121 | "\n", 122 | "Sometimes rather than importing the module namespace, you would just like to import a few particular items from the module.\n", 123 | "This can be done with the \"``from ... import ...``\" pattern.\n", 124 | "For example, we can import just the ``cos`` function and the ``pi`` constant from the ``math`` module:" 125 | ] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "execution_count": 3, 130 | "metadata": { 131 | "collapsed": false 132 | }, 133 | "outputs": [ 134 | { 135 | "data": { 136 | "text/plain": [ 137 | "-1.0" 138 | ] 139 | }, 140 | "execution_count": 3, 141 | "metadata": {}, 142 | "output_type": "execute_result" 143 | } 144 | ], 145 | "source": [ 146 | "from math import cos, pi\n", 147 | "cos(pi)" 148 | ] 149 | }, 150 | { 151 | "cell_type": "markdown", 152 | "metadata": {}, 153 | "source": [ 154 | "### Implicit import of module contents\n", 155 | "\n", 156 | "Finally, it is sometimes useful to import the entirety of the module contents into the local namespace.\n", 157 | "This can be done with the \"``from ... import *``\" pattern:" 158 | ] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "execution_count": 4, 163 | "metadata": { 164 | "collapsed": false 165 | }, 166 | "outputs": [ 167 | { 168 | "data": { 169 | "text/plain": [ 170 | "1.0" 171 | ] 172 | }, 173 | "execution_count": 4, 174 | "metadata": {}, 175 | "output_type": "execute_result" 176 | } 177 | ], 178 | "source": [ 179 | "from math import *\n", 180 | "sin(pi) ** 2 + cos(pi) ** 2" 181 | ] 182 | }, 183 | { 184 | "cell_type": "markdown", 185 | "metadata": {}, 186 | "source": [ 187 | "This pattern should be used sparingly, if at all.\n", 188 | "The problem is that such imports can sometimes overwrite function names that you do not intend to overwrite, and the implicitness of the statement makes it difficult to determine what has changed.\n", 189 | "\n", 190 | "For example, Python has a built-in ``sum`` function that can be used for various operations:" 191 | ] 192 | }, 193 | { 194 | "cell_type": "code", 195 | "execution_count": 5, 196 | "metadata": { 197 | "collapsed": false 198 | }, 199 | "outputs": [ 200 | { 201 | "name": "stdout", 202 | "output_type": "stream", 203 | "text": [ 204 | "Help on built-in function sum in module builtins:\n", 205 | "\n", 206 | "sum(...)\n", 207 | " sum(iterable[, start]) -> value\n", 208 | " \n", 209 | " Return the sum of an iterable of numbers (NOT strings) plus the value\n", 210 | " of parameter 'start' (which defaults to 0). When the iterable is\n", 211 | " empty, return start.\n", 212 | "\n" 213 | ] 214 | } 215 | ], 216 | "source": [ 217 | "help(sum)" 218 | ] 219 | }, 220 | { 221 | "cell_type": "markdown", 222 | "metadata": {}, 223 | "source": [ 224 | "We can use this to compute the sum of a sequence, starting with a certain value (here, we'll start with ``-1``):" 225 | ] 226 | }, 227 | { 228 | "cell_type": "code", 229 | "execution_count": 6, 230 | "metadata": { 231 | "collapsed": false 232 | }, 233 | "outputs": [ 234 | { 235 | "data": { 236 | "text/plain": [ 237 | "9" 238 | ] 239 | }, 240 | "execution_count": 6, 241 | "metadata": {}, 242 | "output_type": "execute_result" 243 | } 244 | ], 245 | "source": [ 246 | "sum(range(5), -1)" 247 | ] 248 | }, 249 | { 250 | "cell_type": "markdown", 251 | "metadata": {}, 252 | "source": [ 253 | "Now observe what happens if we make the *exact same function call* after importing ``*`` from ``numpy``:" 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": 7, 259 | "metadata": { 260 | "collapsed": false 261 | }, 262 | "outputs": [], 263 | "source": [ 264 | "from numpy import *" 265 | ] 266 | }, 267 | { 268 | "cell_type": "code", 269 | "execution_count": 8, 270 | "metadata": { 271 | "collapsed": false 272 | }, 273 | "outputs": [ 274 | { 275 | "data": { 276 | "text/plain": [ 277 | "10" 278 | ] 279 | }, 280 | "execution_count": 8, 281 | "metadata": {}, 282 | "output_type": "execute_result" 283 | } 284 | ], 285 | "source": [ 286 | "sum(range(5), -1)" 287 | ] 288 | }, 289 | { 290 | "cell_type": "markdown", 291 | "metadata": {}, 292 | "source": [ 293 | "The result is off by one!\n", 294 | "The reason for this is that the ``import *`` statement *replaces* the built-in ``sum`` function with the ``numpy.sum`` function, which has a different call signature: in the former, we're summing ``range(5)`` starting at ``-1``; in the latter, we're summing ``range(5)`` along the last axis (indicated by ``-1``).\n", 295 | "This is the type of situation that may arise if care is not taken when using \"``import *``\" – for this reason, it is best to avoid this unless you know exactly what you are doing." 296 | ] 297 | }, 298 | { 299 | "cell_type": "markdown", 300 | "metadata": {}, 301 | "source": [ 302 | "## Importing from Python's Standard Library\n", 303 | "\n", 304 | "Python's standard library contains many useful built-in modules, which you can read about fully in [Python's documentation](https://docs.python.org/3/library/).\n", 305 | "Any of these can be imported with the ``import`` statement, and then explored using the help function seen in the previous section.\n", 306 | "Here is an extremely incomplete list of some of the modules you might wish to explore and learn about:\n", 307 | "\n", 308 | "- ``os`` and ``sys``: Tools for interfacing with the operating system, including navigating file directory structures and executing shell commands\n", 309 | "- ``math`` and ``cmath``: Mathematical functions and operations on real and complex numbers\n", 310 | "- ``itertools``: Tools for constructing and interacting with iterators and generators\n", 311 | "- ``functools``: Tools that assist with functional programming\n", 312 | "- ``random``: Tools for generating pseudorandom numbers\n", 313 | "- ``pickle``: Tools for object persistence: saving objects to and loading objects from disk\n", 314 | "- ``json`` and ``csv``: Tools for reading JSON-formatted and CSV-formatted files.\n", 315 | "- ``urllib``: Tools for doing HTTP and other web requests.\n", 316 | "\n", 317 | "You can find information on these, and many more, in the Python standard library documentation: https://docs.python.org/3/library/." 318 | ] 319 | }, 320 | { 321 | "cell_type": "markdown", 322 | "metadata": {}, 323 | "source": [ 324 | "## Importing from Third-Party Modules\n", 325 | "\n", 326 | "One of the things that makes Python useful, especially within the world of data science, is its ecosystem of third-party modules.\n", 327 | "These can be imported just as the built-in modules, but first the modules must be installed on your system.\n", 328 | "The standard registry for such modules is the Python Package Index (*PyPI* for short), found on the Web at http://pypi.python.org/.\n", 329 | "For convenience, Python comes with a program called ``pip`` (a recursive acronym meaning \"pip installs packages\"), which will automatically fetch packages released and listed on PyPI (if you use Python version 2, ``pip`` must be installed separately).\n", 330 | "For example, if you'd like to install the ``supersmoother`` package that I wrote, all that is required is to type the following at the command line:\n", 331 | "```\n", 332 | "$ pip install supersmoother\n", 333 | "```\n", 334 | "The source code for the package will be automatically downloaded from the PyPI repository, and the package installed in the standard Python path (assuming you have permission to do so on the computer you're using).\n", 335 | "\n", 336 | "For more information about PyPI and the ``pip`` installer, refer to the documentation at http://pypi.python.org/." 337 | ] 338 | }, 339 | { 340 | "cell_type": "markdown", 341 | "metadata": {}, 342 | "source": [ 343 | "\n", 344 | "< [Generators](12-Generators.ipynb) | [Contents](Index.ipynb) | [String Manipulation and Regular Expressions](14-Strings-and-Regular-Expressions.ipynb) >" 345 | ] 346 | } 347 | ], 348 | "metadata": { 349 | "anaconda-cloud": {}, 350 | "kernelspec": { 351 | "display_name": "Python 3", 352 | "language": "python", 353 | "name": "python3" 354 | }, 355 | "language_info": { 356 | "codemirror_mode": { 357 | "name": "ipython", 358 | "version": 3 359 | }, 360 | "file_extension": ".py", 361 | "mimetype": "text/x-python", 362 | "name": "python", 363 | "nbconvert_exporter": "python", 364 | "pygments_lexer": "ipython3", 365 | "version": "3.5.1" 366 | } 367 | }, 368 | "nbformat": 4, 369 | "nbformat_minor": 0 370 | } 371 | -------------------------------------------------------------------------------- /16-Further-Resources.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "*This notebook contains an excerpt from the [Whirlwind Tour of Python](http://www.oreilly.com/programming/free/a-whirlwind-tour-of-python.csp) by Jake VanderPlas; the content is available [on GitHub](https://github.com/jakevdp/WhirlwindTourOfPython).*\n", 10 | "\n", 11 | "*The text and code are released under the [CC0](https://github.com/jakevdp/WhirlwindTourOfPython/blob/master/LICENSE) license; see also the companion project, the [Python Data Science Handbook](https://github.com/jakevdp/PythonDataScienceHandbook).*\n" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "\n", 19 | "< [A Preview of Data Science Tools](15-Preview-of-Data-Science-Tools.ipynb) | [Contents](Index.ipynb) | [Appendix: Figure Code](17-Figures.ipynb) >" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "# Resources for Further Learning" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "This concludes our whirlwind tour of the Python language.\n", 34 | "My hope is that if you read this far, you have an idea of the essential syntax, semantics, operations, and functionality offered by the Python language, as well as some idea of the range of tools and code constructs that you can explore further.\n", 35 | "\n", 36 | "I have tried to cover the pieces and patterns in the Python language that will be most useful to a data scientist using Python, but this has by no means been a complete introduction.\n", 37 | "If you'd like to go deeper in understanding the Python language itself and how to use it effectively, here are a handful of resources I'd recommend:\n", 38 | "\n", 39 | "- [*Fluent Python*](http://shop.oreilly.com/product/0636920032519.do) by Luciano Ramalho. This is an excellent OReilly book that explores best practices and idioms for Python, including getting the most out of the standard library.\n", 40 | "- [*Dive Into Python*](http://www.diveintopython.net/) by Mark Pilgrim. This is a free online book that provides a ground-up introduction to the Python language.\n", 41 | "- [*Learn Python the Hard Way*](http://learnpythonthehardway.org/) by Zed Shaw. This book follows a \"learn by trying\" approach, and deliberately emphasizes developing what may be the most useful skill a programmer can learn: Googling things you don't understand.\n", 42 | "- [*Python Essential Reference*](http://www.dabeaz.com/per.html) by David Beazley. This 700-page monster is well-written, and covers virtually everything there is to know about the Python language and its built-in libraries. For a more application-focused Python walk-through, see Beazley's [*Python Cookbook*](http://shop.oreilly.com/product/0636920027072.do).\n", 43 | "\n", 44 | "To dig more into Python tools for data science and scientific computing, I recommend the following books:\n", 45 | "\n", 46 | "- [*The Python Data Science Handbook*](http://shop.oreilly.com/product/0636920034919.do) by yours truly. This book starts precisely where this report leaves off, and provides a comprehensive guide to the essential tools in Python's data science stack, from data munging and manipulation to machine learning.\n", 47 | "- [*Effective Computation in Physics*](http://shop.oreilly.com/product/0636920033424.do) by Katie Huff and Anthony Scopatz, is applicable to people far beyond the world of Physics research. It is a step-by-step, ground-up introduction to scientific computing, including an excellent introduction to many of the tools mentioned in this report.\n", 48 | "- [*Python for Data Analysis*](http://shop.oreilly.com/product/0636920023784.do) by Wes McKinney, creator of the Pandas package. This book covers the Pandas library in detail, as well as giving useful information on some of the other tools that enable it.\n", 49 | "\n", 50 | "Finally, for an even broader look at what's out there, I recommend the following:\n", 51 | "\n", 52 | "- [*OReilly Python Resources*](http://shop.oreilly.com/category/browse-subjects/programming/python.do) O'Reilly features a number of excellent books on Python itself and specialized topics in the Python world.\n", 53 | "- *PyCon*, *SciPy*, and *PyData*. The PyCon, SciPy, and PyData conferences draw thousands of attendees each year, and archive the bulk of their programs each year as free online videos. These have turned into an incredible set of resources for learning about Python itself, Python packages, and related topics. Search online for videos of both talks and tutorials: the former tend to be shorter, covering new packages or fresh looks at old ones. The tutorials tend to be several hours, covering the use of the tools mentioned here as well as others." 54 | ] 55 | }, 56 | { 57 | "cell_type": "markdown", 58 | "metadata": {}, 59 | "source": [ 60 | "\n", 61 | "< [A Preview of Data Science Tools](15-Preview-of-Data-Science-Tools.ipynb) | [Contents](Index.ipynb) | [Appendix: Figure Code](17-Figures.ipynb) >" 62 | ] 63 | } 64 | ], 65 | "metadata": { 66 | "anaconda-cloud": {}, 67 | "kernelspec": { 68 | "display_name": "Python 3", 69 | "language": "python", 70 | "name": "python3" 71 | }, 72 | "language_info": { 73 | "codemirror_mode": { 74 | "name": "ipython", 75 | "version": 3 76 | }, 77 | "file_extension": ".py", 78 | "mimetype": "text/x-python", 79 | "name": "python", 80 | "nbconvert_exporter": "python", 81 | "pygments_lexer": "ipython3", 82 | "version": "3.5.1" 83 | } 84 | }, 85 | "nbformat": 4, 86 | "nbformat_minor": 0 87 | } 88 | -------------------------------------------------------------------------------- /17-Figures.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "\n", 8 | "\n", 9 | "*This notebook contains an excerpt from the [Whirlwind Tour of Python](http://www.oreilly.com/programming/free/a-whirlwind-tour-of-python.csp) by Jake VanderPlas; the content is available [on GitHub](https://github.com/jakevdp/WhirlwindTourOfPython).*\n", 10 | "\n", 11 | "*The text and code are released under the [CC0](https://github.com/jakevdp/WhirlwindTourOfPython/blob/master/LICENSE) license; see also the companion project, the [Python Data Science Handbook](https://github.com/jakevdp/PythonDataScienceHandbook).*\n" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "\n", 19 | "< [Resources for Further Learning](16-Further-Resources.ipynb) | [Contents](Index.ipynb) |" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "# Appendix: Figure Code" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "This section contains code used to generate figures that appear in this report." 34 | ] 35 | }, 36 | { 37 | "cell_type": "code", 38 | "execution_count": 1, 39 | "metadata": { 40 | "collapsed": true 41 | }, 42 | "outputs": [], 43 | "source": [ 44 | "%matplotlib inline\n", 45 | "import matplotlib.pyplot as plt" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": 2, 51 | "metadata": { 52 | "collapsed": true 53 | }, 54 | "outputs": [], 55 | "source": [ 56 | "import os\n", 57 | "if not os.path.exists('fig'):\n", 58 | " os.makedirs('fig')" 59 | ] 60 | }, 61 | { 62 | "cell_type": "markdown", 63 | "metadata": {}, 64 | "source": [ 65 | "## Section 6: List Indexing\n", 66 | "\n", 67 | "This figure helps visualize how Python's indexing works." 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": 3, 73 | "metadata": { 74 | "collapsed": false 75 | }, 76 | "outputs": [ 77 | { 78 | "data": { 79 | "image/png": "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\n28zMzMwsg/8D+aRsnfmT2tkAAAAASUVORK5CYII=\n", 80 | "text/plain": [ 81 | "" 82 | ] 83 | }, 84 | "metadata": {}, 85 | "output_type": "display_data" 86 | } 87 | ], 88 | "source": [ 89 | "L = [2, 3, 5, 7, 11]\n", 90 | "\n", 91 | "fig = plt.figure(figsize=(10, 4))\n", 92 | "ax = fig.add_axes([0, 0, 1, 1], xticks=[], yticks=[], frameon=False,\n", 93 | " aspect='equal')\n", 94 | "\n", 95 | "for i in range(5):\n", 96 | " ax.add_patch(plt.Rectangle([i - 0.5, -0.5], 1, 1, fc='none', ec='black'))\n", 97 | " ax.text(i, -0.05, L[i], size=100,\n", 98 | " ha='center', va='center', family='monospace')\n", 99 | " \n", 100 | "for i in range(6):\n", 101 | " ax.text(i - 0.5, 0.55, str(i), size=20,\n", 102 | " ha='center', va='bottom', family='monospace')\n", 103 | " \n", 104 | "for i in range(5):\n", 105 | " ax.text(i - 0.5, -0.58, str(-5 + i), size=20,\n", 106 | " ha='center', va='top', family='monospace')\n", 107 | " \n", 108 | "ax.axis([-0.7, 4.7, -0.7, 0.7]);\n", 109 | "\n", 110 | "fig.savefig('fig/list-indexing.png');" 111 | ] 112 | }, 113 | { 114 | "cell_type": "markdown", 115 | "metadata": {}, 116 | "source": [ 117 | "\n", 118 | "< [Resources for Further Learning](16-Further-Resources.ipynb) | [Contents](Index.ipynb) |" 119 | ] 120 | } 121 | ], 122 | "metadata": { 123 | "anaconda-cloud": {}, 124 | "kernelspec": { 125 | "display_name": "Python 3", 126 | "language": "python", 127 | "name": "python3" 128 | }, 129 | "language_info": { 130 | "codemirror_mode": { 131 | "name": "ipython", 132 | "version": 3 133 | }, 134 | "file_extension": ".py", 135 | "mimetype": "text/x-python", 136 | "name": "python", 137 | "nbconvert_exporter": "python", 138 | "pygments_lexer": "ipython3", 139 | "version": "3.5.1" 140 | } 141 | }, 142 | "nbformat": 4, 143 | "nbformat_minor": 0 144 | } 145 | -------------------------------------------------------------------------------- /Index.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# A Whirlwind Tour of Python" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "*Jake VanderPlas*" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": {}, 27 | "source": [ 28 | "These are the Jupyter Notebooks behind my O'Reilly report,\n", 29 | "[*A Whirlwind Tour of Python*](http://www.oreilly.com/programming/free/a-whirlwind-tour-of-python.csp).\n", 30 | "The full notebook listing is available [on Github](https://github.com/jakevdp/WhirlwindTourOfPython).\n", 31 | "\n", 32 | "*A Whirlwind Tour of Python* is a fast-paced introduction to essential\n", 33 | "components of the Python language for researchers and developers who are\n", 34 | "already familiar with programming in another language.\n", 35 | "\n", 36 | "The material is particularly aimed at those who wish to use Python for data \n", 37 | "science and/or scientific programming, and in this capacity serves as an\n", 38 | "introduction to my upcoming book, *The Python Data Science Handbook*.\n", 39 | "These notebooks are adapted from lectures and workshops I've given on these\n", 40 | "topics at University of Washington and at various conferences, meetings, and\n", 41 | "workshops around the world." 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "metadata": {}, 47 | "source": [ 48 | "## Index\n", 49 | "\n", 50 | "1. [Introduction](00-Introduction.ipynb)\n", 51 | "2. [How to Run Python Code](01-How-to-Run-Python-Code.ipynb)\n", 52 | "3. [Basic Python Syntax](02-Basic-Python-Syntax.ipynb)\n", 53 | "4. [Python Semantics: Variables](03-Semantics-Variables.ipynb)\n", 54 | "5. [Python Semantics: Operators](04-Semantics-Operators.ipynb)\n", 55 | "6. [Built-In Scalar Types](05-Built-in-Scalar-Types.ipynb)\n", 56 | "7. [Built-In Data Structures](06-Built-in-Data-Structures.ipynb)\n", 57 | "8. [Control Flow Statements](07-Control-Flow-Statements.ipynb)\n", 58 | "9. [Defining Functions](08-Defining-Functions.ipynb)\n", 59 | "10. [Errors and Exceptions](09-Errors-and-Exceptions.ipynb)\n", 60 | "11. [Iterators](10-Iterators.ipynb)\n", 61 | "12. [List Comprehensions](11-List-Comprehensions.ipynb)\n", 62 | "13. [Generators and Generator Expressions](12-Generators.ipynb)\n", 63 | "14. [Modules and Packages](13-Modules-and-Packages.ipynb)\n", 64 | "15. [Strings and Regular Expressions](14-Strings-and-Regular-Expressions.ipynb)\n", 65 | "16. [Preview of Data Science Tools](15-Preview-of-Data-Science-Tools.ipynb)\n", 66 | "17. [Resources for Further Learning](16-Further-Resources.ipynb)\n", 67 | "18. [Appendix: Code To Reproduce Figures](17-Figures.ipynb)" 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "## License\n", 75 | "\n", 76 | "This material is released under the \"No Rights Reserved\" [CC0](LICENSE)\n", 77 | "license, and thus you are free to re-use, modify, build-on, and enhance\n", 78 | "this material for any purpose.\n", 79 | "\n", 80 | "That said, I request (but do not require) that if you use or adapt this material,\n", 81 | "you include a proper attribution and/or citation; for example\n", 82 | "\n", 83 | "> *A Whirlwind Tour of Python* by Jake VanderPlas (O’Reilly). Copyright 2016 O’Reilly Media, Inc., 978-1-491-96465-1\n", 84 | "\n", 85 | "Read more about CC0 [here](https://creativecommons.org/share-your-work/public-domain/cc0/)." 86 | ] 87 | } 88 | ], 89 | "metadata": { 90 | "anaconda-cloud": {}, 91 | "kernelspec": { 92 | "display_name": "Python 3", 93 | "language": "python", 94 | "name": "python3" 95 | }, 96 | "language_info": { 97 | "codemirror_mode": { 98 | "name": "ipython", 99 | "version": 3 100 | }, 101 | "file_extension": ".py", 102 | "mimetype": "text/x-python", 103 | "name": "python", 104 | "nbconvert_exporter": "python", 105 | "pygments_lexer": "ipython3", 106 | "version": "3.5.1" 107 | } 108 | }, 109 | "nbformat": 4, 110 | "nbformat_minor": 0 111 | } 112 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | 117 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A Whirlwind Tour of Python 2 | 3 | *Jake VanderPlas, Summer 2016* 4 | 5 | This repository contains the Jupyter Notebooks behind my O'Reilly report, 6 | [*A Whirlwind Tour of Python*](http://www.oreilly.com/programming/free/a-whirlwind-tour-of-python.csp) (free [100-page pdf](http://www.oreilly.com/programming/free/files/a-whirlwind-tour-of-python.pdf)). 7 | 8 | *A Whirlwind Tour of Python* is a fast-paced introduction to essential 9 | components of the Python language for researchers and developers who are 10 | already familiar with programming in another language. 11 | 12 | The material is particularly aimed at those who wish to use Python for data 13 | science and/or scientific programming, and in this capacity serves as an 14 | introduction to 15 | [*The Python Data Science Handbook*](http://shop.oreilly.com/product/0636920034919.do) (also 16 | with notebooks [on github](https://github.com/jakevdp/PythonDataScienceHandbook)). 17 | These materials are adapted from courses and workshops I've given on these 18 | topics at University of Washington and at various conferences, meetings, and 19 | workshops around the world. 20 | 21 | This material was written and tested using **Python 3.5**, and should work for any Python 3.X 22 | version. I have done my best to note places where the syntax of Python 2.X will differ. 23 | 24 | ## Index 25 | 26 | *(Note: sometimes GitHub's notebook rendering can be slow or finicky. 27 | If you're having trouble with the following links, try viewing the material 28 | [on nbviewer](http://nbviewer.jupyter.org/github/jakevdp/WhirlwindTourOfPython/blob/master/Index.ipynb))* 29 | 30 | [Notebook Index](http://nbviewer.jupyter.org/github/jakevdp/WhirlwindTourOfPython/blob/master/Index.ipynb) 31 | 32 | 1. [Introduction](http://nbviewer.jupyter.org/github/jakevdp/WhirlwindTourOfPython/blob/master/00-Introduction.ipynb) 33 | 2. [How to Run Python Code](http://nbviewer.jupyter.org/github/jakevdp/WhirlwindTourOfPython/blob/master/01-How-to-Run-Python-Code.ipynb) 34 | 3. [Basic Python Syntax](http://nbviewer.jupyter.org/github/jakevdp/WhirlwindTourOfPython/blob/master/02-Basic-Python-Syntax.ipynb) 35 | 4. [Python Semantics: Variables](http://nbviewer.jupyter.org/github/jakevdp/WhirlwindTourOfPython/blob/master/03-Semantics-Variables.ipynb) 36 | 5. [Python Semantics: Operators](http://nbviewer.jupyter.org/github/jakevdp/WhirlwindTourOfPython/blob/master/04-Semantics-Operators.ipynb) 37 | 6. [Built-In Scalar Types](http://nbviewer.jupyter.org/github/jakevdp/WhirlwindTourOfPython/blob/master/05-Built-in-Scalar-Types.ipynb) 38 | 7. [Built-In Data Structures](http://nbviewer.jupyter.org/github/jakevdp/WhirlwindTourOfPython/blob/master/06-Built-in-Data-Structures.ipynb) 39 | 8. [Control Flow Statements](http://nbviewer.jupyter.org/github/jakevdp/WhirlwindTourOfPython/blob/master/07-Control-Flow-Statements.ipynb) 40 | 9. [Defining Functions](http://nbviewer.jupyter.org/github/jakevdp/WhirlwindTourOfPython/blob/master/08-Defining-Functions.ipynb) 41 | 10. [Errors and Exceptions](http://nbviewer.jupyter.org/github/jakevdp/WhirlwindTourOfPython/blob/master/09-Errors-and-Exceptions.ipynb) 42 | 11. [Iterators](http://nbviewer.jupyter.org/github/jakevdp/WhirlwindTourOfPython/blob/master/10-Iterators.ipynb) 43 | 12. [List Comprehensions](http://nbviewer.jupyter.org/github/jakevdp/WhirlwindTourOfPython/blob/master/11-List-Comprehensions.ipynb) 44 | 13. [Generators and Generator Expressions](http://nbviewer.jupyter.org/github/jakevdp/WhirlwindTourOfPython/blob/master/12-Generators.ipynb) 45 | 14. [Modules and Packages](http://nbviewer.jupyter.org/github/jakevdp/WhirlwindTourOfPython/blob/master/13-Modules-and-Packages.ipynb) 46 | 15. [Strings and Regular Expressions](http://nbviewer.jupyter.org/github/jakevdp/WhirlwindTourOfPython/blob/master/14-Strings-and-Regular-Expressions.ipynb) 47 | 16. [Preview of Data Science Tools](http://nbviewer.jupyter.org/github/jakevdp/WhirlwindTourOfPython/blob/master/15-Preview-of-Data-Science-Tools.ipynb) 48 | 17. [Resources for Further Learning](http://nbviewer.jupyter.org/github/jakevdp/WhirlwindTourOfPython/blob/master/16-Further-Resources.ipynb) 49 | 18. [Appendix: Code To Reproduce Figures](http://nbviewer.jupyter.org/github/jakevdp/WhirlwindTourOfPython/blob/master/17-Figures.ipynb) 50 | 51 | 52 | ## License and Citation 53 | 54 | This material is released under the "No Rights Reserved" [CC0](LICENSE) 55 | license, and thus you are free to re-use, modify, build-on, and enhance 56 | this material for any purpose. 57 | Read more about CC0 [here](https://creativecommons.org/share-your-work/public-domain/cc0/). 58 | 59 | If you do use this material, I would appreciate attribution. 60 | An attribution usually includes the title, author, publisher, and ISBN. 61 | For example: 62 | 63 | > A Whirlwind Tour of Python by Jake VanderPlas (O’Reilly). Copyright 2016 O’Reilly Media, Inc., 978-1-491-96465-1. 64 | -------------------------------------------------------------------------------- /fig/cover-large.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eteh1/WhirlwindTourOfPython/6f1daf714fe52a8dde6a288674ba46a7feed8816/fig/cover-large.gif -------------------------------------------------------------------------------- /fig/cover-small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eteh1/WhirlwindTourOfPython/6f1daf714fe52a8dde6a288674ba46a7feed8816/fig/cover-small.jpg -------------------------------------------------------------------------------- /fig/list-indexing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eteh1/WhirlwindTourOfPython/6f1daf714fe52a8dde6a288674ba46a7feed8816/fig/list-indexing.png -------------------------------------------------------------------------------- /tools/add_book_info.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | 4 | import nbformat 5 | from nbformat.v4.nbbase import new_markdown_cell 6 | 7 | 8 | 9 | BOOK_COMMENT = "" 10 | 11 | 12 | BOOK_INFO = BOOK_COMMENT + """ 13 | 14 | *This notebook contains an excerpt from the [Whirlwind Tour of Python](http://www.oreilly.com/programming/free/a-whirlwind-tour-of-python.csp) by Jake VanderPlas; the content is available [on GitHub](https://github.com/jakevdp/WhirlwindTourOfPython).* 15 | 16 | *The text and code are released under the [CC0](https://github.com/jakevdp/WhirlwindTourOfPython/blob/master/LICENSE) license; see also the companion project, the [Python Data Science Handbook](https://github.com/jakevdp/PythonDataScienceHandbook).* 17 | """ 18 | 19 | NOTEBOOK_DIR = os.path.join(os.path.dirname(__file__), '..') 20 | 21 | REG = re.compile(r'(\d\d)-(.*)\.ipynb') 22 | 23 | 24 | def iter_notebooks(): 25 | return sorted(nb for nb in os.listdir(NOTEBOOK_DIR) if REG.match(nb)) 26 | 27 | 28 | def add_book_info(): 29 | for nb_name in iter_notebooks(): 30 | nb_file = os.path.join(NOTEBOOK_DIR, nb_name) 31 | nb = nbformat.read(nb_file, as_version=4) 32 | 33 | is_comment = lambda cell: cell.source.startswith(BOOK_COMMENT) 34 | 35 | if is_comment(nb.cells[0]): 36 | print('- amending comment for {0}'.format(nb_name)) 37 | nb.cells[0].source = BOOK_INFO 38 | else: 39 | print('- inserting comment for {0}'.format(nb_name)) 40 | nb.cells.insert(0, new_markdown_cell(BOOK_INFO)) 41 | nbformat.write(nb, nb_file) 42 | 43 | 44 | if __name__ == '__main__': 45 | add_book_info() 46 | -------------------------------------------------------------------------------- /tools/add_navigation.py: -------------------------------------------------------------------------------- 1 | import os 2 | import itertools 3 | import re 4 | 5 | from ipykernel import kernelspec as ks 6 | import nbformat 7 | from nbformat.v4.nbbase import new_markdown_cell 8 | 9 | 10 | NOTEBOOK_DIR = os.path.join(os.path.dirname(__file__), '..') 11 | REG = re.compile(r'(\d\d)-(.*)\.ipynb') 12 | 13 | 14 | def iter_notebooks(): 15 | return sorted(nb for nb in os.listdir(NOTEBOOK_DIR) if REG.match(nb)) 16 | 17 | 18 | def get_notebook_title(nb_file): 19 | nb = nbformat.read(os.path.join(NOTEBOOK_DIR, nb_file), as_version=4) 20 | for cell in nb.cells: 21 | if cell.source.startswith('#'): 22 | return cell.source[1:].splitlines()[0].strip() 23 | 24 | 25 | def prev_this_next(it): 26 | a, b, c = itertools.tee(it,3) 27 | next(c) 28 | return zip(itertools.chain([None], a), b, itertools.chain(c, [None])) 29 | 30 | 31 | PREV_TEMPLATE = "< [{title}]({url}) " 32 | CONTENTS = "| [Contents](Index.ipynb) |" 33 | NEXT_TEMPLATE = " [{title}]({url}) >" 34 | NAV_COMMENT = "\n" 35 | 36 | 37 | def iter_navbars(): 38 | for prev_nb, nb, next_nb in prev_this_next(iter_notebooks()): 39 | navbar = NAV_COMMENT 40 | if prev_nb: 41 | navbar += PREV_TEMPLATE.format(title=get_notebook_title(prev_nb), 42 | url=prev_nb) 43 | navbar += CONTENTS 44 | if next_nb: 45 | navbar += NEXT_TEMPLATE.format(title=get_notebook_title(next_nb), 46 | url=next_nb) 47 | yield os.path.join(NOTEBOOK_DIR, nb), navbar 48 | 49 | 50 | def write_navbars(): 51 | for nb_name, navbar in iter_navbars(): 52 | nb = nbformat.read(nb_name, as_version=4) 53 | nb_file = os.path.basename(nb_name) 54 | is_comment = lambda cell: cell.source.startswith(NAV_COMMENT) 55 | 56 | if is_comment(nb.cells[1]): 57 | print("- amending navbar for {0}".format(nb_file)) 58 | nb.cells[1].source = navbar 59 | else: 60 | print("- inserting navbar for {0}".format(nb_file)) 61 | nb.cells.insert(1, new_markdown_cell(source=navbar)) 62 | 63 | if is_comment(nb.cells[-1]): 64 | nb.cells[-1].source = navbar 65 | else: 66 | nb.cells.append(new_markdown_cell(source=navbar)) 67 | nbformat.write(nb, nb_name) 68 | 69 | 70 | if __name__ == '__main__': 71 | write_navbars() 72 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | content/pages/*.md 2 | output 3 | content/figures 4 | content/notebooks -------------------------------------------------------------------------------- /website/Makefile: -------------------------------------------------------------------------------- 1 | PY?=python3 2 | PELICAN?=pelican 3 | PELICANOPTS= 4 | 5 | BASEDIR=$(CURDIR) 6 | INPUTDIR=$(BASEDIR)/content 7 | OUTPUTDIR=$(BASEDIR)/output 8 | CONFFILE=$(BASEDIR)/pelicanconf.py 9 | PUBLISHCONF=$(BASEDIR)/publishconf.py 10 | 11 | FTP_HOST=localhost 12 | FTP_USER=anonymous 13 | FTP_TARGET_DIR=/ 14 | 15 | SSH_HOST=localhost 16 | SSH_PORT=22 17 | SSH_USER=root 18 | SSH_TARGET_DIR=/var/www 19 | 20 | S3_BUCKET=my_s3_bucket 21 | 22 | CLOUDFILES_USERNAME=my_rackspace_username 23 | CLOUDFILES_API_KEY=my_rackspace_api_key 24 | CLOUDFILES_CONTAINER=my_cloudfiles_container 25 | 26 | DROPBOX_DIR=~/Dropbox/Public/ 27 | 28 | GITHUB_PAGES_REMOTE=git@github.com:jakevdp/WhirlwindTourOfPython.git 29 | GITHUB_PAGES_BRANCH=gh-pages 30 | 31 | GIT_COMMIT_HASH = $(shell git rev-parse HEAD) 32 | 33 | DEBUG ?= 0 34 | ifeq ($(DEBUG), 1) 35 | PELICANOPTS += -D 36 | endif 37 | 38 | RELATIVE ?= 0 39 | ifeq ($(RELATIVE), 1) 40 | PELICANOPTS += --relative-urls 41 | endif 42 | 43 | 44 | help: 45 | @echo 'Makefile for a pelican Web site ' 46 | @echo ' ' 47 | @echo 'Usage: ' 48 | @echo ' make html (re)generate the web site ' 49 | @echo ' make clean remove the generated files ' 50 | @echo ' make regenerate regenerate files upon modification ' 51 | @echo ' make publish generate using production settings ' 52 | @echo ' make serve [PORT=8000] serve site at http://localhost:8000' 53 | @echo ' make serve-global [SERVER=0.0.0.0] serve (as root) to $(SERVER):80 ' 54 | @echo ' make devserver [PORT=8000] start/restart develop_server.sh ' 55 | @echo ' make stopserver stop local server ' 56 | @echo ' make ssh_upload upload the web site via SSH ' 57 | @echo ' make rsync_upload upload the web site via rsync+ssh ' 58 | @echo ' make dropbox_upload upload the web site via Dropbox ' 59 | @echo ' make ftp_upload upload the web site via FTP ' 60 | @echo ' make s3_upload upload the web site via S3 ' 61 | @echo ' make cf_upload upload the web site via Cloud Files' 62 | @echo ' make github upload the web site via gh-pages ' 63 | @echo ' ' 64 | @echo 'Set the DEBUG variable to 1 to enable debugging, e.g. make DEBUG=1 html ' 65 | @echo 'Set the RELATIVE variable to 1 to enable relative urls ' 66 | @echo ' ' 67 | 68 | html: 69 | $(PELICAN) $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) 70 | 71 | clean: 72 | [ ! -d $(OUTPUTDIR) ] || rm -rf $(OUTPUTDIR) 73 | 74 | regenerate: 75 | $(PELICAN) -r $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) 76 | 77 | serve: 78 | ifdef PORT 79 | cd $(OUTPUTDIR) && $(PY) -m pelican.server $(PORT) 80 | else 81 | cd $(OUTPUTDIR) && $(PY) -m pelican.server 82 | endif 83 | 84 | serve-global: 85 | ifdef SERVER 86 | cd $(OUTPUTDIR) && $(PY) -m pelican.server 80 $(SERVER) 87 | else 88 | cd $(OUTPUTDIR) && $(PY) -m pelican.server 80 0.0.0.0 89 | endif 90 | 91 | 92 | devserver: 93 | ifdef PORT 94 | $(BASEDIR)/develop_server.sh restart $(PORT) 95 | else 96 | $(BASEDIR)/develop_server.sh restart 97 | endif 98 | 99 | stopserver: 100 | $(BASEDIR)/develop_server.sh stop 101 | @echo 'Stopped Pelican and SimpleHTTPServer processes running in background.' 102 | 103 | publish: 104 | $(PELICAN) $(INPUTDIR) -o $(OUTPUTDIR) -s $(PUBLISHCONF) $(PELICANOPTS) 105 | 106 | ssh_upload: publish 107 | scp -P $(SSH_PORT) -r $(OUTPUTDIR)/* $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR) 108 | 109 | rsync_upload: publish 110 | rsync -e "ssh -p $(SSH_PORT)" -P -rvzc --delete $(OUTPUTDIR)/ $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR) --cvs-exclude 111 | 112 | dropbox_upload: publish 113 | cp -r $(OUTPUTDIR)/* $(DROPBOX_DIR) 114 | 115 | ftp_upload: publish 116 | lftp ftp://$(FTP_USER)@$(FTP_HOST) -e "mirror -R $(OUTPUTDIR) $(FTP_TARGET_DIR) ; quit" 117 | 118 | s3_upload: publish 119 | s3cmd sync $(OUTPUTDIR)/ s3://$(S3_BUCKET) --acl-public --delete-removed --guess-mime-type --no-mime-magic --no-preserve 120 | 121 | cf_upload: publish 122 | cd $(OUTPUTDIR) && swift -v -A https://auth.api.rackspacecloud.com/v1.0 -U $(CLOUDFILES_USERNAME) -K $(CLOUDFILES_API_KEY) upload -c $(CLOUDFILES_CONTAINER) . 123 | 124 | publish-to-github: publish 125 | ghp-import -n -m "publish-to-github from $(GIT_COMMIT_HASH)" -b blog-build $(OUTPUTDIR) 126 | git push $(GITHUB_PAGES_REMOTE) blog-build:$(GITHUB_PAGES_BRANCH) 127 | 128 | publish-to-github-force: publish 129 | ghp-import -n -m "publish-to-github-force from $(GIT_COMMIT_HASH)" -b blog-build $(OUTPUTDIR) 130 | git push -f $(GITHUB_PAGES_REMOTE) blog-build:$(GITHUB_PAGES_BRANCH) 131 | 132 | .PHONY: html help clean regenerate serve serve-global devserver stopserver publish ssh_upload rsync_upload dropbox_upload ftp_upload s3_upload cf_upload github 133 | -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | # Tools for creating http://jakevdp.github.io/WhirlwindTourOfPython/ 2 | 3 | ## Building the Blog 4 | 5 | Clone the repository & make sure submodules are included 6 | 7 | ``` 8 | $ git clone https://github.com/jakevdp/WhirlwindTourOfPython.git 9 | $ git checkout origin/website 10 | $ git submodule update --init --recursive 11 | $ cd website 12 | ``` 13 | 14 | Install the required packages: 15 | 16 | ``` 17 | $ conda create -n pelican-blog python=3.5 jupyter notebook 18 | $ source activate pelican-blog 19 | $ pip install pelican Markdown ghp-import 20 | ``` 21 | 22 | Build the html and serve locally: 23 | 24 | ``` 25 | $ make html 26 | $ make serve 27 | $ open http://localhost:8000 28 | ``` 29 | 30 | Deploy to github pages 31 | 32 | ``` 33 | $ make publish-to-github 34 | ``` -------------------------------------------------------------------------------- /website/content/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eteh1/WhirlwindTourOfPython/6f1daf714fe52a8dde6a288674ba46a7feed8816/website/content/favicon.ico -------------------------------------------------------------------------------- /website/copy_notebooks.py: -------------------------------------------------------------------------------- 1 | """ 2 | This script copies all notebooks from the book into the website directory, and 3 | creates pages which wrap them and link together. 4 | """ 5 | import os 6 | import nbformat 7 | import shutil 8 | 9 | PAGEFILE = """title: {title} 10 | url: 11 | save_as: {htmlfile} 12 | Template: {template} 13 | 14 | {{% notebook notebooks/{notebook_file} cells[{cells}] %}} 15 | """ 16 | 17 | INTRO_TEXT = """ 18 | This website contains the full text of my free O'Reilly report, [*A Whirlwind Tour of Python*](http://www.oreilly.com/programming/free/a-whirlwind-tour-of-python.csp). 19 | 20 | *A Whirlwind Tour of Python* is a fast-paced introduction to essential features of the Python language, aimed at researchers and developers who are already familiar with programming in another language. 21 | The material is particularly designed for those who wish to use Python for data science and/or scientific programming, and in this capacity serves as an introduction to my longer book, [*The Python Data Science Handbook*](http://jakevdp.github.io/PythonDataScienceHandbook). 22 | 23 | The content is also available [on Github](https://github.com/jakevdp/WhirlwindTourOfPython) in the form of Jupyter Notebooks, or from O'Reilly site as a [free e-book](http://www.oreilly.com/programming/free/a-whirlwind-tour-of-python.csp) or [free pdf](http://www.oreilly.com/programming/free/files/a-whirlwind-tour-of-python.pdf). 24 | 25 | This material is released under the "No Rights Reserved" [CC0 license](https://creativecommons.org/share-your-work/public-domain/cc0/), and thus you are free to re-use, modify, build-on, and enhance this material for any purpose. 26 | """ 27 | 28 | 29 | def abspath_from_here(*args): 30 | here = os.path.dirname(__file__) 31 | path = os.path.join(here, *args) 32 | return os.path.abspath(path) 33 | 34 | NB_SOURCE_DIR = abspath_from_here('..') 35 | NB_DEST_DIR = abspath_from_here('content', 'notebooks') 36 | PAGE_DEST_DIR = abspath_from_here('content', 'pages') 37 | 38 | 39 | def copy_notebooks(): 40 | nblist = sorted(nb for nb in os.listdir(NB_SOURCE_DIR) 41 | if nb.endswith('.ipynb')) 42 | name_map = {nb: nb.rsplit('.', 1)[0].lower() + '.html' 43 | for nb in nblist} 44 | 45 | figsource = abspath_from_here('..', 'fig') 46 | figdest = abspath_from_here('content', 'figures') 47 | 48 | if os.path.exists(figdest): 49 | shutil.rmtree(figdest) 50 | shutil.copytree(figsource, figdest) 51 | 52 | figurelist = os.listdir(figdest) 53 | figure_map = {os.path.join('fig', fig) : 54 | os.path.join('/WhirlwindTourOfPython/figures', fig) 55 | for fig in figurelist} 56 | 57 | for nb in nblist: 58 | base, ext = os.path.splitext(nb) 59 | print('-', nb) 60 | 61 | content = nbformat.read(os.path.join(NB_SOURCE_DIR, nb), 62 | as_version=4) 63 | 64 | if nb == 'Index.ipynb': 65 | cells = '1:' 66 | template = 'page' 67 | title = 'A Whirlwind Tour of Python' 68 | content.cells[3].source = INTRO_TEXT 69 | else: 70 | cells = '2:' 71 | template = 'booksection' 72 | title = content.cells[2].source 73 | if not title.startswith('#') or len(title.splitlines()) > 1: 74 | raise ValueError('title not found in third cell') 75 | title = title.lstrip('#').strip() 76 | 77 | # put nav below title 78 | content.cells[0], content.cells[1], content.cells[2] = content.cells[2], content.cells[0], content.cells[1] 79 | 80 | # Replace internal URLs and figure links in notebook 81 | for cell in content.cells: 82 | if cell.cell_type == 'markdown': 83 | for nbname, htmlname in name_map.items(): 84 | if nbname in cell.source: 85 | cell.source = cell.source.replace(nbname, htmlname) 86 | for figname, newfigname in figure_map.items(): 87 | if figname in cell.source: 88 | cell.source = cell.source.replace(figname, newfigname) 89 | 90 | nbformat.write(content, os.path.join(NB_DEST_DIR, nb)) 91 | 92 | pagefile = os.path.join(PAGE_DEST_DIR, base + '.md') 93 | htmlfile = base.lower() + '.html' 94 | with open(pagefile, 'w') as f: 95 | f.write(PAGEFILE.format(title=title, 96 | htmlfile=htmlfile, 97 | notebook_file=nb, 98 | template=template, 99 | cells=cells)) 100 | 101 | if __name__ == '__main__': 102 | copy_notebooks() 103 | 104 | 105 | -------------------------------------------------------------------------------- /website/fabfile.py: -------------------------------------------------------------------------------- 1 | from fabric.api import * 2 | import fabric.contrib.project as project 3 | import os 4 | import shutil 5 | import sys 6 | import SocketServer 7 | 8 | from pelican.server import ComplexHTTPRequestHandler 9 | 10 | # Local path configuration (can be absolute or relative to fabfile) 11 | env.deploy_path = 'output' 12 | DEPLOY_PATH = env.deploy_path 13 | 14 | # Remote server configuration 15 | production = 'root@localhost:22' 16 | dest_path = '/var/www' 17 | 18 | # Rackspace Cloud Files configuration settings 19 | env.cloudfiles_username = 'my_rackspace_username' 20 | env.cloudfiles_api_key = 'my_rackspace_api_key' 21 | env.cloudfiles_container = 'my_cloudfiles_container' 22 | 23 | # Github Pages configuration 24 | env.github_pages_branch = "master" 25 | 26 | # Port for `serve` 27 | PORT = 8000 28 | 29 | def clean(): 30 | """Remove generated files""" 31 | if os.path.isdir(DEPLOY_PATH): 32 | shutil.rmtree(DEPLOY_PATH) 33 | os.makedirs(DEPLOY_PATH) 34 | 35 | def build(): 36 | """Build local version of site""" 37 | local('pelican -s pelicanconf.py') 38 | 39 | def rebuild(): 40 | """`build` with the delete switch""" 41 | local('pelican -d -s pelicanconf.py') 42 | 43 | def regenerate(): 44 | """Automatically regenerate site upon file modification""" 45 | local('pelican -r -s pelicanconf.py') 46 | 47 | def serve(): 48 | """Serve site at http://localhost:8000/""" 49 | os.chdir(env.deploy_path) 50 | 51 | class AddressReuseTCPServer(SocketServer.TCPServer): 52 | allow_reuse_address = True 53 | 54 | server = AddressReuseTCPServer(('', PORT), ComplexHTTPRequestHandler) 55 | 56 | sys.stderr.write('Serving on port {0} ...\n'.format(PORT)) 57 | server.serve_forever() 58 | 59 | def reserve(): 60 | """`build`, then `serve`""" 61 | build() 62 | serve() 63 | 64 | def preview(): 65 | """Build production version of site""" 66 | local('pelican -s publishconf.py') 67 | 68 | def cf_upload(): 69 | """Publish to Rackspace Cloud Files""" 70 | rebuild() 71 | with lcd(DEPLOY_PATH): 72 | local('swift -v -A https://auth.api.rackspacecloud.com/v1.0 ' 73 | '-U {cloudfiles_username} ' 74 | '-K {cloudfiles_api_key} ' 75 | 'upload -c {cloudfiles_container} .'.format(**env)) 76 | 77 | @hosts(production) 78 | def publish(): 79 | """Publish to production via rsync""" 80 | local('pelican -s publishconf.py') 81 | project.rsync_project( 82 | remote_dir=dest_path, 83 | exclude=".DS_Store", 84 | local_dir=DEPLOY_PATH.rstrip('/') + '/', 85 | delete=True, 86 | extra_opts='-c', 87 | ) 88 | 89 | def gh_pages(): 90 | """Publish to GitHub Pages""" 91 | rebuild() 92 | local("ghp-import -b {github_pages_branch} {deploy_path} -p".format(**env)) 93 | -------------------------------------------------------------------------------- /website/pelicanconf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- # 3 | from __future__ import unicode_literals 4 | 5 | AUTHOR = 'Jake VanderPlas' 6 | SITENAME = 'A Whirlwind Tour of Python' 7 | SITESUBTITLE = '' 8 | SITEURL = '' 9 | SITESUBURL = 'WhirlwindTourOfPython/' 10 | PATH = 'content' 11 | TIMEZONE = 'America/Los_Angeles' 12 | DEFAULT_LANG = 'en' 13 | 14 | # Feed generation is usually not desired when developing 15 | FEED_ALL_ATOM = None 16 | CATEGORY_FEED_ATOM = None 17 | TRANSLATION_FEED_ATOM = None 18 | AUTHOR_FEED_ATOM = None 19 | AUTHOR_FEED_RSS = None 20 | 21 | # Set the article URL 22 | ARTICLE_URL = 'blog/{date:%Y}/{date:%m}/{date:%d}/{slug}/' 23 | ARTICLE_SAVE_AS = 'blog/{date:%Y}/{date:%m}/{date:%d}/{slug}/index.html' 24 | 25 | DEFAULT_PAGINATION = 10 26 | 27 | # Uncomment following line if you want document-relative URLs when developing 28 | #RELATIVE_URLS = True 29 | 30 | #MARKUP = ('md', 'ipynb') 31 | #PLUGINS = ['ipynb.markup'] 32 | 33 | MARKUP = ['md'] 34 | PLUGIN_PATHS = ['./plugins', './plugins/pelican-plugins'] 35 | PLUGINS = [ 36 | 'summary', # auto-summarizing articles 37 | 'feed_summary', # use summaries for RSS, not full articles 38 | 'ipynb.liquid', # for embedding notebooks 39 | 'liquid_tags.img', # embedding images 40 | 'liquid_tags.video', # embedding videos 41 | 'liquid_tags.include_code', # including code blocks 42 | 'liquid_tags.literal' 43 | ] 44 | IGNORE_FILES = ['.ipynb_checkpoints'] 45 | 46 | # for liquid tags 47 | CODE_DIR = 'downloads/code' 48 | NOTEBOOK_DIR = 'downloads/notebooks' 49 | 50 | # THEME SETTINGS 51 | THEME = './theme/' 52 | 53 | ABOUT_PAGE = '/pages/about.html' 54 | TWITTER_USERNAME = 'jakevdp' 55 | GITHUB_USERNAME = 'jakevdp' 56 | STACKOVERFLOW_ADDRESS = 'http://stackoverflow.com/users/2937831/jakevdp' 57 | AUTHOR_WEBSITE = 'http://vanderplas.com' 58 | AUTHOR_BLOG = 'http://jakevdp.github.io' 59 | AUTHOR_CV = "http://staff.washington.edu/jakevdp/media/pdfs/CV.pdf" 60 | SHOW_ARCHIVES = True 61 | SHOW_FEED = False # Need to address large feeds 62 | 63 | ENABLE_MATHJAX = True 64 | 65 | STATIC_PATHS = ['images', 'figures', 'videos', 'downloads', 'favicon.ico'] 66 | 67 | # Footer info 68 | 69 | LICENSE_URL = "https://github.com/jakevdp/jakevdp.github.io-source/blob/master/LICENSE" 70 | LICENSE = "MIT" 71 | -------------------------------------------------------------------------------- /website/publishconf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- # 3 | from __future__ import unicode_literals 4 | 5 | # This file is only used if you use `make publish` or 6 | # explicitly specify it as your config file. 7 | 8 | import os 9 | import sys 10 | sys.path.append(os.curdir) 11 | from pelicanconf import * 12 | 13 | SITEURL = 'http://jakevdp.github.io/WhirlwindTourOfPython' 14 | RELATIVE_URLS = False 15 | 16 | SHOW_FEED = False 17 | FEED_ALL_ATOM = 'feeds/all.atom.xml' 18 | CATEGORY_FEED_ATOM = 'feeds/%s.atom.xml' 19 | FEED_USE_SUMMARY = True # from the feed_summary plugin 20 | 21 | DELETE_OUTPUT_DIRECTORY = True 22 | 23 | DISQUS_SITENAME = "pythonicperambulations" 24 | GOOGLE_ANALYTICS = "UA-34061646-1" 25 | -------------------------------------------------------------------------------- /website/theme/README.md: -------------------------------------------------------------------------------- 1 | # Pythonic Perambulations Theme 2 | 3 | This theme was adapted from that at https://github.com/danielfrg/danielfrg.github.io-source; the original is released under the Apache v2.0 license. 4 | Adaptations are contained in this directory. -------------------------------------------------------------------------------- /website/theme/static/css/icons.css: -------------------------------------------------------------------------------- 1 | /* Copied from https://github.com/porterjamesj/crowsfoot */ 2 | 3 | @font-face { 4 | font-family: 'icons'; 5 | src: url('../font/icons.eot?79801659'); 6 | src: url('../font/icons.eot?79801659#iefix') format('embedded-opentype'), 7 | url('../font/icons.woff?79801659') format('woff'), 8 | url('../font/icons.ttf?79801659') format('truetype'), 9 | url('../font/icons.svg?79801659#icons') format('svg'); 10 | font-weight: normal; 11 | font-style: normal; 12 | } 13 | /* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */ 14 | /* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */ 15 | /* 16 | @media screen and (-webkit-min-device-pixel-ratio:0) { 17 | @font-face { 18 | font-family: 'icons'; 19 | src: url('../font/icons.svg?79801659#icons') format('svg'); 20 | } 21 | } 22 | */ 23 | 24 | [class^="icon-"]:before, [class*=" icon-"]:before { 25 | font-family: "icons"; 26 | font-style: normal; 27 | font-weight: normal; 28 | speak: none; 29 | 30 | display: inline-block; 31 | text-decoration: inherit; 32 | width: 1em; 33 | margin-right: .2em; 34 | text-align: center; 35 | /* opacity: .8; */ 36 | 37 | /* For safety - reset parent styles, that can break glyph codes*/ 38 | font-variant: normal; 39 | text-transform: none; 40 | 41 | /* fix buttons height, for twitter bootstrap */ 42 | line-height: 1em; 43 | 44 | /* Animation center compensation - margins should be symmetric */ 45 | /* remove if not needed */ 46 | margin-left: .2em; 47 | 48 | /* you can be more comfortable with increased icons size */ 49 | /* font-size: 120%; */ 50 | 51 | /* Uncomment for 3D effect */ 52 | /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ 53 | } 54 | 55 | .icon-stackoverflow:before { content: '\e032'; } /* '' */ 56 | .icon-twitter:before { content: '\e801'; } /* '' */ 57 | .icon-facebook:before { content: '\e802'; } /* '' */ 58 | .icon-rss:before { content: '\e800'; } /* '' */ 59 | .icon-mail-alt:before { content: '\f0e0'; } /* '' */ 60 | .icon-github:before { content: '\f113'; } /* '' */ -------------------------------------------------------------------------------- /website/theme/static/font/icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eteh1/WhirlwindTourOfPython/6f1daf714fe52a8dde6a288674ba46a7feed8816/website/theme/static/font/icons.eot -------------------------------------------------------------------------------- /website/theme/static/font/icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Copyright (C) 2012 by original authors @ fontello.com 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /website/theme/static/font/icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eteh1/WhirlwindTourOfPython/6f1daf714fe52a8dde6a288674ba46a7feed8816/website/theme/static/font/icons.ttf -------------------------------------------------------------------------------- /website/theme/static/font/icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eteh1/WhirlwindTourOfPython/6f1daf714fe52a8dde6a288674ba46a7feed8816/website/theme/static/font/icons.woff -------------------------------------------------------------------------------- /website/theme/templates/_includes/analytics.html: -------------------------------------------------------------------------------- 1 | {% if GOOGLE_UNIVERSAL_ANALYTICS %} 2 | 11 | {% elif GOOGLE_ANALYTICS %} 12 | 30 | {% endif %} 31 | -------------------------------------------------------------------------------- /website/theme/templates/_includes/disqus_thread.html: -------------------------------------------------------------------------------- 1 | {% if DISQUS_SITENAME and SITEURL and article.status != "draft" %} 2 |
3 |

Comments

4 |
5 | 16 |
17 | {% endif %} 18 | -------------------------------------------------------------------------------- /website/theme/templates/about.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}{{ page.title }}{% endblock %} 3 | {% block headerimg %}{% if page.headerimg %}{{ page.headerimg }}{% else %}{{ DEFAULT_HEADER_BG }}{% endif %}{% endblock %} 4 | 5 | {% block content %} 6 | 7 |
8 |
9 |
10 |

{{ page.title }}

11 | {% if page.date %} 12 | 13 | {% endif %} 14 |
36 | 37 |
38 | {{ page.content }} 39 |
40 | 41 |
42 |
43 | {% endblock %} 44 | -------------------------------------------------------------------------------- /website/theme/templates/archives.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}Archives{% endblock %} 3 | {% block headerimg %}{{ DEFAUT_HEADER_BG }}{% endblock %} 4 | 5 | {% block content %} 6 |
7 | 27 |
28 | {% endblock %} 29 | -------------------------------------------------------------------------------- /website/theme/templates/article.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}{{ article.title }}{% endblock %} 3 | {% block headerimg %}{% if article.headerimg %}{{ article.headerimg }}{% else %}{{ DEFAULT_HEADER_BG }}{% endif %}{% endblock %} 4 | 5 | {% block extra_head %} 6 | {% if 'angular' in article.include %} 7 | 8 | {% endif %} 9 | {% if 'jquery' in article.include %} 10 | 11 | {% endif %} 12 | {% endblock %} 13 | 14 | {% block content %} 15 |
16 |
17 |
18 |

{{ article.title }}

19 | 20 |
21 | 22 |
23 | {{ article.content }} 24 |
25 | 26 |
27 |
28 | {% for tag in article.tags %} 29 | {{ tag }} 30 | {% endfor %} 31 |
32 |
33 |
34 | 35 | {% include '_includes/disqus_thread.html' %} 36 | 37 |
38 | 39 | 42 | 43 | {% endblock %} 44 | -------------------------------------------------------------------------------- /website/theme/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {% block title %}{% endblock %} | {{ SITENAME }} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | {% if ENABLE_MATHJAX %} 25 | 26 | 45 | {% endif %} 46 | 47 | {% block extra_head %}{%endblock%} 48 | 49 | 50 | 51 | 79 | 80 |
81 | {% block content %}{% endblock %} 82 |
83 | 92 | {% include '_includes/analytics.html' %} 93 | 94 | 95 | -------------------------------------------------------------------------------- /website/theme/templates/booksection.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}{{ page.title }}{% endblock %} 3 | {% block headerimg %}{% if page.headerimg %}{{ page.headerimg }}{% else %}{{ DEFAULT_HEADER_BG }}{% endif %}{% endblock %} 4 | 5 | {% block content %} 6 | 7 |
8 |

9 | 10 | This notebook contains an excerpt from the Whirlwind Tour of Python by Jake VanderPlas; the content is available on GitHub.

11 |

The text and code are released under the CC0 license; see also the companion project, the Python Data Science Handbook.

12 |
13 | 14 | 15 |
16 | 17 |
18 |
19 |

{{ page.title }}

20 | {% if page.date %} 21 | 22 | {% endif %} 23 |
24 | 25 |
26 | {{ page.content }} 27 |
28 | 29 |
30 |
31 | {% endblock %} 32 | -------------------------------------------------------------------------------- /website/theme/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}Home{% endblock %} 3 | {% block headerimg %}{{ DEFAULT_HEADER_BG }}{% endblock %} 4 | 5 | {% block content %} 6 |
7 | 8 | {% for article in articles_page.object_list %} 9 |
10 |
11 |

{{ article.title }}

12 | 13 |
14 | 15 |
16 | {{ article.summary }} 17 |
18 | 19 |
20 |
21 | Read more → 22 |
23 | 24 |
25 | {% for tag in article.tags %} 26 | {{ tag }} 27 | {% endfor %} 28 |
29 | 30 |
31 | 32 |
33 |
34 | {% endfor %} 35 | 36 | 48 | 49 |
50 | 51 | 52 | 53 | {% endblock %} 54 | -------------------------------------------------------------------------------- /website/theme/templates/ipynb.css: -------------------------------------------------------------------------------- 1 | { 2 | max-width: 700px; 3 | } 4 | 5 | .text_cell .prompt { 6 | display: none; 7 | } 8 | 9 | div.cell { 10 | padding: 0; 11 | } 12 | 13 | div.text_cell_render { 14 | padding: 0; 15 | } 16 | 17 | div.prompt { 18 | font-size: 13px; 19 | } 20 | 21 | div.input_prompt { 22 | padding: .7em 0.2em; 23 | } 24 | 25 | div.output_prompt { 26 | padding: .4em .2em; 27 | } 28 | 29 | div.input_area { 30 | margin: .2em 0.4em; 31 | max-width: 580px; 32 | } 33 | 34 | table.dataframe { 35 | font-family: Arial, sans-serif; 36 | font-size: 13px; 37 | line-height: 20px; 38 | } 39 | 40 | table.dataframe th, td { 41 | padding: 4px; 42 | text-align: left; 43 | } 44 | 45 | pre code { 46 | background-color: inherit; 47 | } 48 | -------------------------------------------------------------------------------- /website/theme/templates/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font: 15px 'Source Sans Pro', sans-serif; 5 | line-height: 1.6em; 6 | color: #222; 7 | text-rendering: optimizeLegibility; 8 | -webkit-font-smoothing: antialiased; 9 | } 10 | a { 11 | color: #007EE5; 12 | text-decoration: none; 13 | } 14 | a:hover { 15 | color: #007EE5; 16 | text-decoration: none; 17 | } 18 | header.main-header { 19 | background: none repeat scroll 0% 0% #205F29; 20 | margin-bottom: 0px; 21 | } 22 | header.main-header a { 23 | color: #fff; 24 | } 25 | header.main-header .container { 26 | max-width: 1000px; 27 | } 28 | header.main-header .container nav a:hover { 29 | background-color: #5C881C; 30 | } 31 | article { 32 | margin: 0; 33 | } 34 | article header.about { 35 | margin-bottom: 0px; 36 | padding-bottom: 0px; 37 | } 38 | article header { 39 | margin-bottom: 20px; 40 | padding-bottom: 20px; 41 | } 42 | article header h1 { 43 | margin-bottom: 2px; 44 | font-weight: 700; 45 | color: #000; 46 | } 47 | article header time { 48 | color: #9E9E9E; 49 | font-size: 0.85em; 50 | float: right; 51 | } 52 | article header time.left { 53 | color: #9E9E9E; 54 | font-size: 0.85em; 55 | float: left; 56 | } 57 | article div.social-links ul { 58 | padding: 0px; 59 | } 60 | article div.social-links li { 61 | display: inline; 62 | font-size: 20px; 63 | } 64 | article div.social-links li a { 65 | color: #000; 66 | padding: 10px; 67 | } 68 | article div.social-links li a:hover { 69 | color: #666; 70 | text-decoration: none; 71 | } 72 | article p { 73 | font-size: 16px; 74 | margin-bottom: 20px; 75 | line-height: 1.6em; 76 | } 77 | article p.note { 78 | background: #f5f5f5; 79 | border: 1px solid #ddd; 80 | padding: 0.533em 0.733em; 81 | } 82 | article p.update { 83 | background-color: #FEEFB3; 84 | border: 1px solid #e6e68a; 85 | padding: 0.533em 0.733em; 86 | } 87 | article p.alert { 88 | background-color: #ffe2e2; 89 | border: 1px solid #ffb2b2; 90 | padding: 0.533em 0.733em; 91 | } 92 | article ul, 93 | article ol { 94 | margin-top: 0px; 95 | margin-bottom: 25px; 96 | } 97 | article li { 98 | font-size: 16px; 99 | line-height: 1.6em; 100 | } 101 | article a:hover { 102 | text-decoration: underline; 103 | } 104 | article blockquote { 105 | border-left: 2px solid #c7c7cc; 106 | color: #666; 107 | margin: 30px 0; 108 | padding: 0 0 0 25px; 109 | } 110 | article img { 111 | max-width: 100%; 112 | } 113 | article code { 114 | color: #333; 115 | background-color: #EEE; 116 | border-radius: 0; 117 | font-size: 13px; 118 | } 119 | article .meta { 120 | font-size: 11px; 121 | } 122 | article .meta a:hover { 123 | text-decoration: none; 124 | } 125 | article .meta div { 126 | margin-bottom: 20px; 127 | display: block; 128 | } 129 | article .meta a.tag { 130 | margin: 0 10px 10px 0; 131 | padding: 1px 12px; 132 | display: inline-block; 133 | font-size: 14px; 134 | color: rgba(0, 0, 0, 0.8); 135 | background: rgba(0, 0, 0, 0.05); 136 | } 137 | article .meta a.tag:hover { 138 | background: rgba(0, 0, 0, 0.15); 139 | } 140 | article .meta a.read_more, 141 | article .meta a.comments_btn { 142 | font-size: 14px; 143 | font-weight: 800; 144 | padding: 10px 20px; 145 | color: #205F29; 146 | background: #FFF; 147 | border: 1px solid #205F29; 148 | } 149 | article .meta a.read_more:hover, 150 | article .meta a.comments_btn:hover { 151 | color: #FFF; 152 | background: #5C881C; 153 | } 154 | .index { 155 | max-width: 700px; 156 | } 157 | .index article header h2 { 158 | font-size: 36px; 159 | margin-bottom: 2px; 160 | font-weight: 700; 161 | } 162 | .index article header h2 a { 163 | color: #000; 164 | } 165 | .index article header h2 a:hover { 166 | color: #007EE5; 167 | text-decoration: none; 168 | } 169 | .index .separator { 170 | padding: 40px 0 0 0; 171 | margin: 0 0 40px 0; 172 | height: 10px; 173 | border-bottom: solid 1px #CCC; 174 | } 175 | .index .pagination { 176 | display: block; 177 | margin-bottom: 100px; 178 | } 179 | .index .pagination .left { 180 | text-align: right; 181 | } 182 | .index .pagination .right { 183 | text-align: left; 184 | } 185 | .index .pagination a { 186 | display: inline-block; 187 | border: 2px solid #5C881C; 188 | margin: 0 5px; 189 | padding: 8px 20px; 190 | font-weight: bold; 191 | color: #5C881C; 192 | } 193 | .index .pagination a:hover { 194 | color: #FFF; 195 | background: #5C881C; 196 | } 197 | .post { 198 | max-width: 700px; 199 | } 200 | .post h2:before { 201 | content: "# "; 202 | font-weight: bold; 203 | color: #DDD; 204 | } 205 | .post h3:before { 206 | content: "## "; 207 | font-weight: bold; 208 | color: #DDD; 209 | } 210 | .post h4:before { 211 | content: "### "; 212 | font-weight: bold; 213 | color: #DDD; 214 | } 215 | .post article .meta { 216 | margin: 50px 0 100px; 217 | } 218 | .list { 219 | max-width: 700px; 220 | } 221 | .list ul.double-list { 222 | margin: 0 auto 60px; 223 | padding: 0; 224 | list-style-type: none; 225 | } 226 | .list ul.double-list li { 227 | padding: 5px 0; 228 | } 229 | .list ul.double-list li h2 { 230 | font-size: 1em; 231 | display: inline; 232 | font-weight: normal; 233 | } 234 | .list ul.double-list li span { 235 | font-family: sans-serif; 236 | text-transform: uppercase; 237 | text-align: right; 238 | float: right; 239 | padding-top: 3px; 240 | font-size: 12px; 241 | color: #999; 242 | } 243 | .full-width-content { 244 | padding-top: 10px; 245 | padding-left: 0px; 246 | padding-right: 0px; 247 | margin-left: -20px; 248 | margin-right: -20px; 249 | } 250 | .col-xs-1, 251 | .col-sm-1, 252 | .col-md-1, 253 | .col-lg-1, 254 | .col-xs-2, 255 | .col-sm-2, 256 | .col-md-2, 257 | .col-lg-2, 258 | .col-xs-3, 259 | .col-sm-3, 260 | .col-md-3, 261 | .col-lg-3, 262 | .col-xs-4, 263 | .col-sm-4, 264 | .col-md-4, 265 | .col-lg-4, 266 | .col-xs-5, 267 | .col-sm-5, 268 | .col-md-5, 269 | .col-lg-5, 270 | .col-xs-6, 271 | .col-sm-6, 272 | .col-md-6, 273 | .col-lg-6, 274 | .col-xs-7, 275 | .col-sm-7, 276 | .col-md-7, 277 | .col-lg-7, 278 | .col-xs-8, 279 | .col-sm-8, 280 | .col-md-8, 281 | .col-lg-8, 282 | .col-xs-9, 283 | .col-sm-9, 284 | .col-md-9, 285 | .col-lg-9, 286 | .col-xs-10, 287 | .col-sm-10, 288 | .col-md-10, 289 | .col-lg-10, 290 | .col-xs-11, 291 | .col-sm-11, 292 | .col-md-11, 293 | .col-lg-11, 294 | .col-xs-12, 295 | .col-sm-12, 296 | .col-md-12, 297 | .col-lg-12 { 298 | padding-right: 0px; 299 | padding-left: 0px; 300 | } 301 | -------------------------------------------------------------------------------- /website/theme/templates/main.less: -------------------------------------------------------------------------------- 1 | // out: ./main.css, compress: true 2 | 3 | @text-color: #222; 4 | @link-color: #007EE5; 5 | 6 | body { 7 | margin: 0; 8 | padding: 0; 9 | font: 15px 'Source Sans Pro', sans-serif; 10 | line-height: 1.6em; 11 | color: @text-color; 12 | text-rendering: optimizeLegibility; 13 | -webkit-font-smoothing: antialiased; 14 | } 15 | 16 | a { 17 | color: @link-color; 18 | text-decoration: none; 19 | } 20 | 21 | a:hover { 22 | color: @link-color; 23 | text-decoration: none; 24 | } 25 | 26 | header.main-header { 27 | background: none repeat scroll 0% 0% #205F29; 28 | margin-bottom: 0px; 29 | 30 | a { 31 | color: #fff; 32 | } 33 | 34 | .container { 35 | max-width: 1000px; 36 | 37 | nav { 38 | a:hover { 39 | background-color: #5C881C; 40 | } 41 | } 42 | } 43 | } 44 | 45 | article { 46 | margin: 0; 47 | 48 | header.about { 49 | margin-bottom: 0px; 50 | padding-bottom: 0px; 51 | } 52 | 53 | header { 54 | margin-bottom: 20px; 55 | padding-bottom: 20px; 56 | 57 | h1 { 58 | margin-bottom: 2px; 59 | font-weight: 700; 60 | color: #000; 61 | } 62 | 63 | time { 64 | color: #9E9E9E; 65 | font-size: 0.85em; 66 | float: right; 67 | } 68 | 69 | time.left { 70 | color: #9E9E9E; 71 | font-size: 0.85em; 72 | float: left; 73 | } 74 | } 75 | 76 | div.social-links { 77 | ul { 78 | padding: 0px; 79 | } 80 | li { 81 | display: inline; 82 | font-size: 20px; 83 | a { 84 | color: #000; 85 | padding: 10px; 86 | } 87 | a:hover { 88 | color: #666; 89 | text-decoration: none; 90 | } 91 | } 92 | } 93 | 94 | p { 95 | font-size: 16px; 96 | margin-bottom: 20px; 97 | line-height: 1.6em; 98 | } 99 | 100 | p.note { 101 | background: #f5f5f5; 102 | border: 1px solid #ddd; 103 | padding: 0.533em 0.733em; 104 | } 105 | 106 | p.update { 107 | background-color: #FEEFB3; 108 | border: 1px solid #e6e68a; 109 | padding: 0.533em 0.733em; 110 | } 111 | 112 | p.alert { 113 | background-color: #ffe2e2; 114 | border: 1px solid #ffb2b2; 115 | padding: 0.533em 0.733em; 116 | } 117 | 118 | ul, ol { 119 | margin-top: 0px; 120 | margin-bottom: 25px; 121 | } 122 | 123 | li { 124 | font-size: 16px; 125 | line-height: 1.6em; 126 | } 127 | 128 | a:hover { 129 | text-decoration: underline; 130 | } 131 | 132 | blockquote { 133 | border-left: 2px solid #c7c7cc; 134 | color: #666; 135 | margin: 30px 0; 136 | padding: 0 0 0 25px; 137 | } 138 | 139 | img { 140 | max-width: 100%; 141 | } 142 | 143 | code { 144 | color: #333; 145 | background-color: #EEE; 146 | border-radius: 0; 147 | font-size: 13px; 148 | } 149 | 150 | .meta { 151 | font-size: 11px; 152 | 153 | a:hover { 154 | text-decoration: none; 155 | } 156 | 157 | div { 158 | margin-bottom: 20px; 159 | display: block; 160 | } 161 | 162 | a.tag { 163 | margin: 0 10px 10px 0; 164 | padding: 1px 12px; 165 | display: inline-block; 166 | font-size: 14px; 167 | color: rgba(0,0,0,0.8);; 168 | background: rgba(0,0,0,0.05); 169 | } 170 | 171 | a.tag:hover { 172 | background: rgba(0,0,0,0.15); 173 | } 174 | 175 | a.read_more, a.comments_btn { 176 | font-size: 14px; 177 | font-weight: 800; 178 | padding: 10px 20px; 179 | color: #205F29; 180 | background: #FFF; 181 | border: 1px solid #205F29; 182 | } 183 | 184 | a.read_more:hover, a.comments_btn:hover { 185 | color: #FFF; 186 | background: #5C881C; 187 | } 188 | } 189 | } 190 | 191 | .index { 192 | max-width: 700px; 193 | 194 | article { 195 | header { 196 | h2 { 197 | font-size: 36px; 198 | margin-bottom: 2px; 199 | font-weight: 700; 200 | 201 | a { 202 | color: #000; 203 | } 204 | a:hover { 205 | color: @link-color; 206 | text-decoration: none; 207 | } 208 | } 209 | } 210 | } 211 | 212 | .separator { 213 | padding: 40px 0 0 0; 214 | margin: 0 0 40px 0; 215 | height: 10px; 216 | border-bottom: solid 1px #CCC; 217 | } 218 | 219 | .pagination { 220 | display: block; 221 | margin-bottom: 100px; 222 | 223 | .left { 224 | text-align: right; 225 | } 226 | 227 | .right { 228 | text-align: left; 229 | } 230 | 231 | a { 232 | display: inline-block; 233 | border: 2px solid #5C881C; 234 | margin: 0 5px; 235 | padding: 8px 20px; 236 | font-weight: bold; 237 | color: #5C881C; 238 | } 239 | 240 | a:hover { 241 | color: #FFF; 242 | background: #5C881C; 243 | } 244 | } 245 | } 246 | 247 | .post { 248 | max-width: 700px; 249 | 250 | h2:before { 251 | content: "# "; 252 | font-weight: bold; 253 | color: #DDD; 254 | } 255 | 256 | h3:before { 257 | content: "## "; 258 | font-weight: bold; 259 | color: #DDD; 260 | } 261 | 262 | h4:before { 263 | content: "### "; 264 | font-weight: bold; 265 | color: #DDD; 266 | } 267 | 268 | article { 269 | .meta { 270 | margin: 50px 0 100px; 271 | } 272 | } 273 | } 274 | 275 | .list { 276 | max-width: 700px; 277 | 278 | ul.double-list { 279 | margin: 0 auto 60px; 280 | padding: 0; 281 | list-style-type: none; 282 | 283 | li { 284 | padding: 5px 0; 285 | 286 | h2 { 287 | font-size: 1em; 288 | display: inline; 289 | font-weight: normal; 290 | } 291 | 292 | span { 293 | font-family: sans-serif; 294 | text-transform: uppercase; 295 | text-align: right; 296 | float: right; 297 | padding-top: 3px; 298 | font-size: 12px; 299 | color: #999; 300 | } 301 | } 302 | } 303 | } 304 | 305 | .full-width-content { 306 | padding-top: 10px; 307 | padding-left: 0px; 308 | padding-right: 0px; 309 | margin-left: -20px; 310 | margin-right: -20px; 311 | } 312 | 313 | .col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { 314 | padding-right: 0px; 315 | padding-left: 0px; 316 | } 317 | -------------------------------------------------------------------------------- /website/theme/templates/page.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}{{ page.title }}{% endblock %} 3 | {% block headerimg %}{% if page.headerimg %}{{ page.headerimg }}{% else %}{{ DEFAULT_HEADER_BG }}{% endif %}{% endblock %} 4 | 5 | {% block content %} 6 |
7 | 8 |
9 |
10 |

{{ page.title }}

11 | {% if page.date %} 12 | 13 | {% endif %} 14 |
15 | 16 |
17 | {{ page.content }} 18 |
19 | 20 |
21 |
22 | {% endblock %} 23 | -------------------------------------------------------------------------------- /website/theme/templates/pygments.css: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #ffffcc } 2 | .highlight .c { color: #60a0b0; font-style: italic } /* Comment */ 3 | .highlight .err { border: 1px solid #FF0000 } /* Error */ 4 | .highlight .k { color: #007020; font-weight: bold } /* Keyword */ 5 | .highlight .o { color: #666666 } /* Operator */ 6 | .highlight .cm { color: #60a0b0; font-style: italic } /* Comment.Multiline */ 7 | .highlight .cp { color: #007020 } /* Comment.Preproc */ 8 | .highlight .c1 { color: #60a0b0; font-style: italic } /* Comment.Single */ 9 | .highlight .cs { color: #60a0b0; background-color: #fff0f0 } /* Comment.Special */ 10 | .highlight .gd { color: #A00000 } /* Generic.Deleted */ 11 | .highlight .ge { font-style: italic } /* Generic.Emph */ 12 | .highlight .gr { color: #FF0000 } /* Generic.Error */ 13 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 14 | .highlight .gi { color: #00A000 } /* Generic.Inserted */ 15 | .highlight .go { color: #808080 } /* Generic.Output */ 16 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ 17 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 18 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 19 | .highlight .gt { color: #0040D0 } /* Generic.Traceback */ 20 | .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ 21 | .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ 22 | .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ 23 | .highlight .kp { color: #007020 } /* Keyword.Pseudo */ 24 | .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ 25 | .highlight .kt { color: #902000 } /* Keyword.Type */ 26 | .highlight .m { color: #40a070 } /* Literal.Number */ 27 | .highlight .s { color: #4070a0 } /* Literal.String */ 28 | .highlight .na { color: #4070a0 } /* Name.Attribute */ 29 | .highlight .nb { color: #007020 } /* Name.Builtin */ 30 | .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ 31 | .highlight .no { color: #60add5 } /* Name.Constant */ 32 | .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ 33 | .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ 34 | .highlight .ne { color: #007020 } /* Name.Exception */ 35 | .highlight .nf { color: #06287e } /* Name.Function */ 36 | .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ 37 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ 38 | .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ 39 | .highlight .nv { color: #bb60d5 } /* Name.Variable */ 40 | .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ 41 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 42 | .highlight .mf { color: #40a070 } /* Literal.Number.Float */ 43 | .highlight .mh { color: #40a070 } /* Literal.Number.Hex */ 44 | .highlight .mi { color: #40a070 } /* Literal.Number.Integer */ 45 | .highlight .mo { color: #40a070 } /* Literal.Number.Oct */ 46 | .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ 47 | .highlight .sc { color: #4070a0 } /* Literal.String.Char */ 48 | .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ 49 | .highlight .s2 { color: #4070a0 } /* Literal.String.Double */ 50 | .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ 51 | .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ 52 | .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ 53 | .highlight .sx { color: #c65d09 } /* Literal.String.Other */ 54 | .highlight .sr { color: #235388 } /* Literal.String.Regex */ 55 | .highlight .s1 { color: #4070a0 } /* Literal.String.Single */ 56 | .highlight .ss { color: #517918 } /* Literal.String.Symbol */ 57 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ 58 | .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ 59 | .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ 60 | .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ 61 | .highlight .il { color: #40a070 } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /website/theme/templates/tag.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}Archives{% endblock %} 3 | {% block headerimg %}{{ DEFAUT_HEADER_BG }}{% endblock %} 4 | 5 | {% block content %} 6 |
7 | 21 |
22 | {% endblock %} 23 | --------------------------------------------------------------------------------