diff --git a/.idea/HiPyProject.iml b/.idea/HiPyProject.iml
deleted file mode 100644
index d0876a7..0000000
--- a/.idea/HiPyProject.iml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 5bbe586..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 63b27af..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 94a25f7..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
deleted file mode 100644
index 8eb4239..0000000
--- a/.idea/workspace.xml
+++ /dev/null
@@ -1,104 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 1557812616712
-
-
- 1557812616712
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/CNAME b/CNAME
deleted file mode 100644
index e9f93a9..0000000
--- a/CNAME
+++ /dev/null
@@ -1 +0,0 @@
-hipy.uk
diff --git a/Machine Learning Helper Notebook.ipynb b/Machine Learning Helper Notebook.ipynb
deleted file mode 100644
index e759a75..0000000
--- a/Machine Learning Helper Notebook.ipynb
+++ /dev/null
@@ -1,116 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Machine Learning Hive Beekeeper Notebook\n",
- "\n",
- "This is a working notebook for common questions/information about the Machine Learning modules and hives. While writing this, I've gone through the modules again and tried to answer any questions I think might come up here, so you won't have to fiddle around with google on the day - of course, I'll probably miss things so feel free to add stuff!\n",
- "\n",
- "This module has a few aims:\n",
- "\n",
- "* Explain some common algorithms, the thinking behind them and how they can be applied to real world problems.\n",
- "* To get people used to using 3rd party \"black box\" libraries, and to start to understand why libraries are so helpful in general.\n",
- "* To give illustrations of how powerful data analysis/science is using Python (or indeed any other coding language).\n",
- "* To serve as a soft introduction into the world of neural networks if people want to go down that route.\n",
- "\n",
- "It's organised as one algorithm per notebook, in a very simple format of explaining the algorithm, example code, and a project that is slightly more challenging than the example but shouldn't be unreasonable given the person doing it has a solid foundation of Python. Naturally I think the first questions people will ask are:\n",
- "\n",
- "### Why do machine learning over statistics?\n",
- "\n",
- "Machine learning and statistics are similar areas, and often use the same methods in finding an answer (for example, regression), but the difference comes from their implementation in Python - machine learning libraries such as scikitlearn will build a model object we can make predictions from, whereas stats libraries like scipy and statsmodels are more useful for getting statistical summaries like test statistics and p-values. In practice, it depends on the application - if you are running an experiment and need to see the correlation between two variables, you will probably want to use a statistics package, but if you are building a model to predict where earthquakes might hit, you will probably want to use machine learning.\n",
- "\n",
- "### It's all good knowing these models - but what model do I need to apply?\n",
- "\n",
- "A lot of this depends on what you are trying to achieve and what data you have - do we want to categorise data into sets or do we want to find a continuous relationship between them? Do we need the results to be fast or accurate? Do we have a training set we can use the model for? All of these questions help us decide what model we want to use (sometimes the answer isn't just to slam it into a neural network!)\n",
- "\n",
- "# K Means Clustering\n",
- "\n",
- "### How do I choose k? Surely there has to be a better way than the elbow method?\n",
- "\n",
- "This is where knowledge of your field comes in - for example, if you are trying to cluster population centers, you will use k values that make sense for the area (number of cities etc).\n",
- "\n",
- "### What's going on with the make_blobs function?\n",
- "\n",
- "Get them to print everything the make_blobs function give us - it will give a list, with the points in the first index, and a lot of stuff we don't need (in fact, the list is the list which gives a corresponece from each point to the blob it belongs in!). For our example, we don't want to other stuff, so we just index it out.\n",
- "\n",
- "### What's the indexing trick?\n",
- "\n",
- "Our data is a 2 column matrix - each row is a point which we want to plot - since matplotlib wants a list of x coordinates then a list of y coordinates, we need to format the data to get it into a position we can use the plot function on it. The indexing in numpy works by giving what is basically a list of slices - since we want to index all rows we put the empty slice \":\" in the first spot, and \"0\" for the second spot because we only want everything from the first column. Similarly, we use [:,1] for the y values because we want every row, but every second value for each row.\n",
- "\n",
- "Also consider the native Python equivilent and how they would do it then using indexing and/or for loops. It's much more of a pain!\n",
- "\n",
- "### Completely confused about the \"model\" variable, what does it mean?\n",
- "\n",
- "This is a product of object orientated programming - we actually initialise a k means model for 4 centers using the KMeans() function, and then fit it to our data using the fit method. This is a method on the model object - not a function - so the model \"changes itself\" to fit our data. What's important to realise is all the information we need is stored inside the model object, we don't get it from running functions on it!\n",
- "\n",
- "\n",
- "### How can I do Mini Project 1 if the data is 4 dimensional?\n",
- "\n",
- "The great thing about the algorithm is that it's generalised - we don't care about what these points represent (see project 2), and how many dimensions our data points have - the reason this is a 4 dimensional example is to remove the crutch of geometric representation - you have to trust in the code! \n",
- "\n",
- "The solution for this Mini Project is pretty much identical for the example but backwards - we want to use the elbow method first to find a suitable K and then build a model using the suitable k. People who are struggling might try and guess for values of K - try and get these people to think about why that might not be a good idea (model always gets better for larger k, but that's not the point of the model! We don't want to overfit). People who are excelling through this might wonder if there's a better way of finding a K-value suitable for our data. In fact, there is a better algorithm for when we don't know our K-value called the DBSCAN method - but I haven't written this guide yet!\n",
- "\n",
- "### How do I get started on Mini Project 2? There's no numbers!\n",
- "\n",
- "Explain how RGB values work - everything else pretty much follows from here - I think it's a numpy function to convert a picture to RGB\n",
- "\n",
- "### What is K for Mini Project 2?\n",
- "\n",
- "If we want to quantise for 16 colours - what does this mean?\n",
- "\n",
- "\n",
- "# K Nearest Neighbours\n",
- "\n",
- "Most of the questions above also apply to this guide - I decided to move a bit faster at this point because I'm expecting people to be getting more comfortable with numpy and pandas at this point. The most confusion will come from the illustration of KNN - I think people will be able to understand it at this point but might need some help understanding certain bits of the code. The idea is that we set upper and lower bounds for x and y based on our data, with a buffer of 1 so the graph has a bit of space, then set up a meshgrid, which is basically a 2 dimensional matrix with each point on the graph being represented. We then need to format this a little to get it into (x,y) pairs, which we will have one of for each point on the graph. Then we predict every one of these points and plot it behind our actual data to show the boundry.\n",
- "\n",
- "# Support Vector Machines\n",
- "\n",
- "### Why use this vs the KNN algorithm?\n",
- "\n",
- "First priority is data - if you need a linear seperation between your data KNN isn't going to give you that. Other than that, SVM is a much slower algorithm than KNN, so if we don't need to be accurate but need to be fast, then SVM might not be appropriate.\n",
- "\n",
- "# Decision Trees\n",
- "\n",
- "### Why use it?\n",
- "\n",
- "Gives us a fast model that we can use as humans to classify data even if it's multidimensional. Great when speed and explaination are needed over a \"black box\" and accuracy!\n",
- "\n",
- "### How do I get those fancy visualiations?\n",
- "\n",
- "Honestly, this took me the best part of 4 hours to do. Get them to google it and figure it out for their system - knowing how these events run nothing will run the same on my system compared to anyone elses!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.3"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/PurePy 0. Woffle and Getting Started/.ipynb_checkpoints/0.1 Introduction-checkpoint.ipynb b/PurePy 0. Woffle and Getting Started/.ipynb_checkpoints/0.1 Introduction-checkpoint.ipynb
deleted file mode 100644
index 77fca81..0000000
--- a/PurePy 0. Woffle and Getting Started/.ipynb_checkpoints/0.1 Introduction-checkpoint.ipynb
+++ /dev/null
@@ -1,182 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# What is Python?\n",
- "\n",
- "Ever wanted to learn to code? Maybe there are some tasks you do over and over that you'd love to get a computer to do them for you. Perhaps you've got an idea for an app, but no way to make it happen. Or maybe you've heard that coding is an important skill in today's economy and want to get ahead. Maybe you're just curious.\n",
- "\n",
- "Or maybe you already know how to code? Perhaps you know one of the heavy-duty langauges like C++ or Java, but want something more fun for you smaller projects. Perhaps you're a science student raised on MATLAB, looking for a more widely available alternative for when you get out in the real world.\n",
- "\n",
- "Python is a free programming language created and maintained by Dutch programmer Guido Von Rossom. It's designed designed to be easy to read and learn, with many aspects of the language reading like English, and many technical aspects of programming handled \"behind the scenes\". This makes Python a great first language, and its quick-and-easy approach makes it a great tool even for seasoned programmers.\n",
- "\n",
- "The other side of the coin of \"what is Python?\" is analogous to the other side of the question \"What is English?\". On the one hand, it is a Germanic language, originating in England and spoken throughout the world. On the other, it is the canon of literature written in English, and the community of English speakers. Similarly, Python is the vast array of Python code that has already been written, much of it freely available online, so that other programmers may find it useful. These Python \"libraries\" offer tools for almost everything, from creating websites to analysing DNA sequences.\n",
- "\n",
- "Computers don't understand programming languages. They understand machine code, which is basically unreadable to humans. Therefore, a program must translate the source code, written in Python or another programming language, into machine code, which the computer can understand. This software for us is called a Python interpreter. We will sometimes be lazy with our language, and refer to the Python interpreter simply as \"Python\", as in \"Python won't understand what you mean if you type this wrong\", or \"Run Python\" (meaning \"Run a Python interpreter\").\n",
- "\n",
- "At HiPy, we recommend installing [Anaconda](https://www.continuum.io/downloads), which is the regular Python interpreter and standard library, plus many more great libraries and development tools. It's a big download, but having all the best tools right in front of you from the start is worth the payoff, in our opinion.\n",
- "\n",
- "\n",
- "# Three main ways to execute Python code\n",
- "\n",
- "So, let's assume you've installed Python (there we go already, lazily referring to the standard Python interpreter + libaries as \"Python\"), possibly via Anaconda. How do we get stuff to happen? Well, there are three main ways that you can start using Python right now. Each has different advantages for different situations.\n",
- "\n",
- "### Quick start note: Don't care about this stuff and want to just get on with PurePy 1? Run Spyder from the Anaconda launcher. Type code on the left of the screen, and hit $\\blacktriangleright$ to run it. The result will appear on the right.\n",
- "\n",
- "## Interactively\n",
- "\n",
- "Once Python is correctly installed, opening a command-line interface (see PurePy 0.2 for more on the command-line) and typing python will bring up something that looks like this:"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "Python 3.6.1 |Anaconda 4.4.0 (64-bit)| (default, May 11 2017, 13:09:58) \n",
- "[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux\n",
- "Type \"help\", \"copyright\", \"credits\" or \"license\" for more information.\n",
- ">>>"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This is the interactive Python shell, and those three little >'s mean Python is ready to talk to you. You can type anything in here, and the interpreter will try to read it as if it is Python code. It will execute the line of code you typed, and then tell you the result.\n",
- "\n",
- "So the stuff we type has to be Python code. We cannot just say \"hello\", but if we do, nothing bad will happen. The interpreter just lets us know that this is not what it was expecting."
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- ">>> Hello Python!\n",
- " File \"\", line 1\n",
- " Hello Python!\n",
- " ^\n",
- "SyntaxError: invalid syntax\n",
- ">>>"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Try some arithmetic. The Python shell understands this at the very least:"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- ">>> 5 / 2\n",
- "2.5\n",
- ">>>"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The interactive interface for Python has three main uses:\n",
- "\n",
- "- Performing very quick computations.\n",
- "- Testing bits of code before adding them to a big program.\n",
- "- Interacting with a program you've already written.\n",
- "\n",
- "The downsides are that you can't easily save what you've done. Without some effort, both your code and results are gone at the end of your session. This furthermore means that larger programming endeavours are unfeasible, because you can't just save your code and come back later.\n",
- "\n",
- "### IPython vs. Python\n",
- "\n",
- "An alternative version of the interactive Python interpreter exists called IPython, and it comes installed with Anaconda. It has loads of extra features to make inteteractive computing with Python easier, faster, and more readable. Both run the same code in the same way. The only downside, as I see it, to IPython is that it takes a few moments longer to start up.\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Scripts: Editor + Interpreter\n",
- "\n",
- "So interactive computing is all well and good. But most of the time we want to write a larger program, that can perform more elaborate tasks, and we don't want to have to feed each step to the interpreter one at a time.\n",
- "\n",
- "So the alternative is to write all your code in a file, and then pass it to the Python interpreter to read through and execute. The Python file is called Python script, or Python module. Any software that can write a file of text can be used to write a Python module, but some are more suited to this task than others.\n",
- "\n",
- "### Important note\n",
- "\n",
- "When you are using Python interactively, the result of every computation is written to the screen as output. If you are running a Python script written in a text file, which may be thousands of lines long, it is unlikely that you will want to see the result of every single computation along the way. To see the result of a computation, use the print() command, for example, print(5 / 2) will display 2.5 to the screen.\n",
- "\n",
- "### IDEs\n",
- "\n",
- "An IDE is an \"integrated development environment\". Generally this means it's a piece of software that brings all the tools needed to write a program under one roof. So, the IDE will contain a text editor, for writing code. It may include a terminal, so you can access your computer's command line interface. It may include a Python interpreter, as well as debugging tools, version control, a file manager, and anything else a developer might need.\n",
- "\n",
- "\n",
- "\n",
- "Included with Anaconda, Spyder is a perfectly fine IDE to start with that runs the IPython interface alongside the editor window. If you installed Anaconda, this is an easy way for you to get started! If, after a while, you're looking for something with more features, try PyCharm. If you're looking for something with less features that loads faster, try Geany.\n",
- "\n",
- "### Text editors\n",
- "\n",
- "While IDEs provide many conveniences, many Python programmers prefer to edit text in a specialized programming text editor, and then run their program from the command-line. A good text editor is really, really good at efficiently editing text. The various extra features provided by IDEs can be handled with other programs. At the very least, a programming text editor should have syntax highlighting, in which the text is displayed in different colours to show the structure of the program.\n",
- "\n",
- "A great choice for a programming text editor is [Atom](https://atom.io/), for any system, or [Notepad++](https://notepad-plus-plus.org/download/v6.9.1.html) if you're on Windows. Some popular text editors, like VIM and Emacs, are very powerful, but take days to learn to use -- learn Python first before deciding if it is worth your investment!\n",
- "\n",
- "\n",
- "\n",
- "If you choose this approach, definitely check out PurePy 0.2 about the command-line.\n",
- "\n",
- "Once you have written your text file, save it with the extension .py. Then you can go to your command line, navigate to the directory containing that file, and type python fileyoujustmade.py to run it.\n",
- "\n",
- "## Jupyter Notebook\n",
- "\n",
- "This is a sort of hybrid between interactive and scripted Python. It is the Jupyter notebook, in which this document was created. Think of it as an interactive document, which talks to a Python interpreter and allows code to be written and executed, displaying the output within the document itself. It also, of course, allows segments of text to explain the code, supports $\\LaTeX$ for mathematical typesetting, and can display picture and other media. This makes Jupyter notebook great for data analysis, as your methodology (your code) and results (plots and such) can be displayed together in a single document. You can launch Juypter notebook from Anaconda, or from the command line with the command jupyter-notebook.\n",
- "\n",
- "Many online services, such as [CoCalc](www.cocalc.com) or [Azure](https://notebooks.azure.com/) offer online and collaborative Jupyter notebooks.\n",
- "\n",
- "To get started on Jupyter, write code in a cell, and hit shift+return to execute the code in the cell. If you want a cell to contain text, use the dropdown menu at the top of the screen to switch the cell type from \"Code\" to \"Markdown\"."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# What next?\n",
- "\n",
- "If you want to get started learning some Python programming now, skip ahead to PurePy 1. Alternatively, PurePy 0.2 provides a crash course in command-line computing, an important secondary skill for anyone doing programming. However, you will not lose out if you skip it for now and come back to it later, since presumably you came to HiPy to learn Python!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.1"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/PurePy 0. Woffle and Getting Started/.ipynb_checkpoints/0.2 The command line-checkpoint.ipynb b/PurePy 0. Woffle and Getting Started/.ipynb_checkpoints/0.2 The command line-checkpoint.ipynb
deleted file mode 100644
index e306d2c..0000000
--- a/PurePy 0. Woffle and Getting Started/.ipynb_checkpoints/0.2 The command line-checkpoint.ipynb
+++ /dev/null
@@ -1,473 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# The command line: a very short introduction\n",
- "\n",
- "This article is not about Python. But it is worth the time of any new Python programmer, or anyone who uses computers a lot. We have to have a discussion about the command-line. Most of us in the modern era have grown up using a graphical user interface (GUI) to interact with our computers. This is where we use a mouse or touch screen to press on-screen buttons, drag-and-drop files, highlight text, move a scroll bar, or bring up a menu. But there is another method, in which we interact with the computer by typing in text commands, and getting text output. For many, this is an ancient relic seen only in films such as The Matrix, War Games, or Hackers, but in the world of computers and computer programming, it remains an invaluable tool.\n",
- "\n",
- "Now the command-line isn't pretty, and takes a little practice to learn. Most commercial software is no longer written for the command-line for this reason. But as Python beginners, we're generally going to be writing programs that:\n",
- "1. Takes some input,\n",
- "2. Performs some task or computation,\n",
- "3. Gives some output,\n",
- "\n",
- "rather than writing commercial software. For this purpose, a text-based, command-line is quicker, easier, and just as effective.\n",
- "\n",
- "Reasons to learn basic command-line skills:\n",
- "- Command-line software is easier to write than graphical software.\n",
- "- Many tasks easier and faster with the command-line.\n",
- "- Access to vast repositories of free command-line software.\n",
- "- More freedom to tinker with the workings of your computer.\n",
- "- Feel like a hacker.\n",
- "\n",
- "That said, there are still many tasks which lend themselves better to the graphical interface. I don't know many people, for instance, who manage their emails from the command-line (though such people almost certainly exist). It's just about choosing the correct tool for the job."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Before we begin, three basic terms. A command-line is any computer interface in which you type text and get text back. A terminal or terminal emulator is a piece of software on your computer that displays the text for a command-line interface. Finally, a shell is the software \"behind the scenes\", that interprets your commands, performs the tasks you ask of it, and then displays the result in your terminal. These words are sometimes used somewhat interchangeably. Something like \"type this command into the command-line\", \"type this command into the terminal\", \"type this command into the shell\" all mean basically the same thing."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Accessing a command-line\n",
- "\n",
- "The precise software you use will depend on your operating system. If it is at all possible, you should try to use the Bash shell. This has become the standard shell across Mac OSX and Linux operating systems. It is now also available as an experimental feature of Windows 10: see [here](https://www.howtogeek.com/249966/how-to-install-and-use-the-linux-bash-shell-on-windows-10/) for installation instructions. If you are on Windows, but either you do not have Windows 10 or you do not want to install Bash for some reason, then you can use a software that comes with Windows call Powershell. The most basic commands of Powershell and Bash are roughly the same, and most of the things we learn in this tutorial are applicable to Bash and Powershell.\n",
- "\n",
- "* On Windows, either follow the Bash instructions above, or go to the Start Menu, type Powershell, and open the software it suggests. Note that in Powershell you might have to use backslashes instead of slashes for file paths.\n",
- "* On OSX, press cmd+space. This will open the spotlight, which can access any file or program on your computer. Type Terminal, and you will shown the correct software on the menu. Consider adding the terminal to your dock, as it is very useful to have quick access.\n",
- "* On Linux systems, go to whatever interface you usually use to open software. If you're on Ubuntu or GNOME or something, try the gnome-terminal, usually accessible just be typing \"Terminal\". If you are on another operating system, you might not have gnome-terminal, but you will definitely have xterm or some equivalent, so try searching for xterm.\n",
- "\n",
- "Now after allowing everything to load, you should see some kind of command-prompt. On Powershell, I think it will end with a > symbol. In Bash, it will probably be a $ sign. This means the command-line is ready to take commands."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Will I break my computer?\n",
- "\n",
- "Probably not. There are several checks to make sure you do not do anything dangerous unwittingly. The command for deleting files requires special permissions to delete entire folders, for example. In Bash, many commands that involve installing software, changing important settings or modifying key system files will require you to log-in as an administrator or enter an administrator password before proceeding (even if you are already logged in as an administrator in your normal graphical session).\n",
- "\n",
- "## Anatomy of a command\n",
- "\n",
- "A command has the structure \"command options arguments\". The command is a program we'd like to run, or an action we'd like to take. For example, if I open my terminal and simply type firefox, then it opens my web browser. Many commands and programs run inside the terminal, unlike Firefox. Options are things we can add to change the way the command works, often beginning with a - or --, and then a letter or word (for example, it is common in Bash that to get help for using a program, you follow the name of the command with --help. Finally, the arguments are inputs to a command.\n",
- "\n",
- "As an example, a very simple Bash program called cat can be used to show the contents of a text file in the terminal window. If I just type cat, then the program waits for me to type some text for it to display. If I type cat A_FILE_NAME, then the contents of that file will be displayed: the file name is an argument, an input to the program. Finally, as an example of using it with an option, cat --number A_FILE_NAME. This will display the contents of a file with line numbers shown.\n",
- "\n",
- "You can usually see what the options are for a program by running PROGRAM_NAME --help or running man PROGRAM_NAME, that is, the program \"manuals\" with the name of the program you want help with as an argument."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## The working directory\n",
- "\n",
- "The first command we will learn is pwd, which stands for \"print working directory\". This means \"print onto the screen\", not \"print from your printer\". The working directory is the folder in your computer that you are currently \"in\", just like on a graphical file browser (My Computer, Finder, nautilus, etc), you are usually viewing and manipulating the contents of just one folder.\n",
- "\n",
- "For instance, when I open my terminal and type pwd, I have something like:"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "$ pwd\n",
- "/home/sam"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This shows us where we currently are in our computer's file system. The natural thing to want to do is to view the contents of the current working directory. Just type ls, which is short for \"list\", if I'm not mistaken. Now you should see the contents of the current directory, possibly with colour coding to show different kinds of file if your terminal is fancy enough."
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "$ ls\n",
- "Desktop Pictures\n",
- "Documents Public\n",
- "Downloads Templates\n",
- "Music Videos"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Cool, so now we are starting to orientate ourselves in our computer. In Bash, there are many useful options for ls. For example, ls -a is \"list all\", which shows hidden files (usually files containing settings for programs, which you will only edit occasionally and otherwise get in the way. Hidden files start with a .). You can use ls -l for a more detailed list with file sizes and such. Options that are of one letter can often be joined into one option, so ls -l -a can be ls -la, which will display a detailed list of all the files in your directory.\n",
- "\n",
- "If you provide a path to a directory to ls as an argument, it will list the contents of that directory instead:"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "$ ls Documents\n",
- "Personal\n",
- "Work\n",
- "Articles\n",
- "Letters"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Changing directory\n",
- "\n",
- "Now we learn how to navigate. The command cd, when given a directory as an argument, will change the current working directory. Example:"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "$ pwd\n",
- "/home/sam\n",
- "$ cd Documents\n",
- "$ pwd\n",
- "/home/sam/Documents"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You can go \"up\" a directory by navigating to ..:"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "$ pwd\n",
- "/home/sam\n",
- "$ cd Documents\n",
- "$ pwd\n",
- "/home/sam/Documents\n",
- "$ cd ..\n",
- "$ pwd\n",
- "/home/sam"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "If you need to refer to a folder or file with spaces in, put the file name in quote marks."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Relative and absolute paths\n",
- "\n",
- "So far, we have used relative file paths. This is where the \"route\" taken to the desired directory or file is relative to the current working directory. In the above example, cd Documents took me to Documents because Documents is contained in the current working directory. If my current working directory were, say, home/sam/Pictures, then to navigate to the Documents directory in one move, I could use cd ../Documents, meaning \"go up one level, and then go to Documents\".\n",
- "\n",
- "However, I can also use what is called an absolute path. This is an exact address, always referring to the same file or directory regardless of the current working directory. In Mac OSX/Linux, starting a path with / makes it absolute. Hence if I am in the Pictures folder (or indeed ANY folder) and want to go to Documents, I can always type"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "$ cd /home/sam/Documents\n",
- "$ pwd\n",
- "/home/sam/Documents"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "On Windows Powershell, you can give an absolute path by starting the path with the drive name, like"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "> cd C:\\Users\\Sam\\Documents"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Making a new directory\n",
- "\n",
- "The command to make a new directory is mkdir, and the directory name is provided as an argument:"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "$ ls\n",
- "Desktop Pictures\n",
- "Documents Public\n",
- "Downloads Templates\n",
- "Music Videos\n",
- "$ mkdir python-scripts\n",
- "$ ls\n",
- "Desktop python-scripts\n",
- "Documents Public\n",
- "Downloads Templates\n",
- "Music Videos\n",
- "Pictures "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Note that I chose to use a - instead of a space in my directory name. As a regular user of the command line, this makes it easier to type as I don't have to remember to put it in quotes this way."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Tab completion\n",
- "\n",
- "One of the nicest features about modern command-lines is that they often allow tab completion. Pressing the TAB key when partway through a command or file in the current directory will complete the command for you, if there is only one possibility. For example, in my /home/sam directory, typing cd Doc and hitting TAB will complete the command to cd Documents. This allows for much more rapid navigation and manipulation.\n",
- "\n",
- "## Move, copy, or rename a file\n",
- "\n",
- "It may surprise you that on the command-line, moving and renaming files are the very same command. It's quite simple really. The mv command takes two arguments: the first, a source file; the second, a target. If the target is a directory, the file is moved to that directory"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Delete a file\n",
- "\n",
- "Delete a file with the command rm, followed by the name of the file relative to the current working directory. If you want to delete a folder, you will have to use rm -r DIRECTORY_NAME. This -r stands for \"recursive\" and means \"delete the contents and the folder\"."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Make a new text file\n",
- "\n",
- "In bash, you can use the command nano followed by a file name (if it doesn't exist it will be created) to open the nano text editor, an easy-to-use terminal-based text editor. Here you can type a Python file, or any other text file you like. The basic commands are given at the bottom (the ^ sign refers to the ctrl key, so to save (\"write out\") a file is ctrl+O. The text editor has syntax highlighting based on the file name, so ending the file name with .py will enable Python highlighting; in other words, the colours will change to reflect the structure of Python code, if you terminal supports colours.\n",
- "\n",
- "On Windows Powershell, you can use notepad.exe FILENAME to achieve a similar end."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Access Python\n",
- "\n",
- "Well, now we get to the business end. You know how to navigate through your computer and even write a Python program using nano. If Python is installed correctly, and your shell knows where it is, typing python should open the interactive Python interpreter, a command-line interface with a shell that understands Python commands, rather than Bash or Powershell commands. You should see something like this. The >>> means it is ready to start interpreting Python commands."
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "$ python\n",
- "Python 3.6.1 |Anaconda 4.4.0 (64-bit)| (default, May 11 2017, 13:09:58) \n",
- "Type \"copyright\", \"credits\" or \"license\" for more information.\n",
- ">>>"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "From here, we can type any valid Python code and the program will run it. Since we don't know any Python yet, just test it by asking it \"2 + 2\":"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- ">>> 2 + 2\n",
- "4"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now we can leave by typing exit().\n",
- "\n",
- "Next we'll learn how to run a Python program that you have already written. Type nano hello.py or notepad.exe hello.py. This has made a new Python file. In the file, write"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "print(\"Hello world!\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "and save it (ctrl+O in nano), then exit (ctrl+X in nano). This program, if written correctly, will write \"Hello world!\" on the screen.\n",
- "\n",
- "Then, when in the working directory in which you saved the file, type:"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "$ python hello.py\n",
- "Hello world!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Hence, python is the program, and hello.py is the argument provided. Now you know how to run any Python file, even one you have downloaded from the Internet.\n",
- "\n",
- "### Did you get an error when you typed python, even though you installed it fine?\n",
- "\n",
- "It means that python is not in your shell's PATH variable. Don't worry. The idea is, when you type a command, it would be very slow (and risky) for the shell to just search your entire computer for some program that command could refer to. Instead, there is a list called PATH of places the shell should look to find programs.\n",
- "\n",
- "So, to solve this, you must find where you have installed Python, and then tell your computer that it's okay to look here when you give it a command.\n",
- "\n",
- "If you're using Bash:\n",
- "1. Navigate to your home folder. The quick way is cd ~, since ~ always refers to your home folder, for convenience.\n",
- "2. You need to edit a file called .bashrc. The ., recall, means it is a hidden file. This is just a file that contains settings for your Bash sessions.\n",
- "3. Hence, type nano .bashrc. There might already be a bunch of stuff in here. If you're feeling bored but brave sometime, feel free to back up this file and have a play around to see what happens.\n",
- "4. Scroll down to the bottom of the file. Add the line:\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "export PATH=\"/path/to/folder/where/python/is/installed:$PATH\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This just means \"change the PATH variable to '/path/to/where/python/is/installed' followed by whatever the PATH variable was before\". Save the file and exit, then type exit into Bash. Open the terminal again and Python should work.\n",
- "\n",
- "If you're using Windows Powershell\n",
- "\n",
- "Type into Powershell\n",
- "\n",
- "[Environment]::SetEnvironmentVariable(\"Path\", \"$env:Path;C:\\path\\to\\folder\\where\\python\\is\\installed\")\n",
- "\n",
- "This should solve it.\n",
- "\n",
- "If neither of these work, I'm afraid you'll have to get your Google-fu on."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Still a bit baffled? Check out the video\n",
- "\n",
- "All of these basic commands are demonstrated in the video below. You'll see that it's pretty easy once you get going.\n",
- "\n",
- "\n",
- "If you're interested in learning more about how to use Bash and become a command-line expert, there's a great free e-book called The Linux Command Line by William E. Shotts Jr."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- " \n",
- " "
- ],
- "text/plain": [
- ""
- ]
- },
- "execution_count": 1,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "from IPython.display import YouTubeVideo\n",
- "YouTubeVideo(\"poUKA4pOn7k\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Exercise\n",
- "\n",
- "From the command line, create a folder in your home directory for \"Python-and-computer-notes\" or something. In here, use the nano text editor to write a short summary of everything you learned here, and save it for future reference."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.1"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/PurePy 11. Exceptions/.ipynb_checkpoints/Exceptions, and debugging-checkpoint.ipynb b/PurePy 11. Exceptions/.ipynb_checkpoints/Exceptions, and debugging-checkpoint.ipynb
deleted file mode 100644
index 194531e..0000000
--- a/PurePy 11. Exceptions/.ipynb_checkpoints/Exceptions, and debugging-checkpoint.ipynb
+++ /dev/null
@@ -1,452 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Handling exceptions, and debugging\n",
- "\n",
- "## Exceptions\n",
- "\n",
- "So far, errors have been the bane of our lives. We pass the wrong kind of argument to a function, we make an accidental division by 0, or we try to access a list element that doesn't exist. The whole program crashes, and we're frustrated trying to find out what went wrong.\n",
- "\n",
- "Now we can turn this situation on its head. Python lets us anticipate places where errors might occur, and allows us to tell the program what to do if it encounters an error, instead of coming grinding to a halt. In other words, we can put our errors to work for us.\n",
- "\n",
- "\"Great!\" you might be thinking. \"I'll just ignore all errors!\" Not so fast, of course. The point of error messages is they tell us where our program is going wrong and prevents more serious problems happening further down the line. We want to be informed when an unexpected error occurs as that means there's something wrong with our program. What exception handling allows us to do is manage the errors that we do expect to happen from time to time. This means our exception handling should be carefully tailored to the circumstances."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### raise\n",
- "\n",
- "The raise keyword is followed by the name of an exception (a procedure that occurs when an error occurs), and causes that kind of exception to occur. We can also provide an error message to go with the error"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [
- {
- "ename": "TypeError",
- "evalue": "This is the wrong type of thing",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"This is the wrong type of thing\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;31mTypeError\u001b[0m: This is the wrong type of thing"
- ]
- }
- ],
- "source": [
- "raise TypeError(\"This is the wrong type of thing\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This can be used along with if statements to only raise the exception under specific circumstances. Suppose I have a function that is supposed to operate on lists:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "def acts_on_a_list(a_list):\n",
- " for x in a_list:\n",
- " print(x)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now before calling that function, I might write:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "ename": "TypeError",
- "evalue": "letters variable should be a list",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0mletters\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m'S'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'a'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'm'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mletters\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"letters variable should be a list\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m \u001b[0macts_on_a_list\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mletters\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;31mTypeError\u001b[0m: letters variable should be a list"
- ]
- }
- ],
- "source": [
- "letters = ('S', 'a', 'm')\n",
- "if not isinstance(letters, list):\n",
- " raise TypeError(\"letters variable should be a list\")\n",
- "acts_on_a_list(letters)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now you see, I have anticipated that my function might receive the wrong kind of input at this stage, and given the user an error message to explain what they are doing wrong.\n",
- "\n",
- "## try, except, finally\n",
- "\n",
- "Astute reads will have noticed that actually, my function acts_on_a_list() doesn't require a list at all. It could take as its input anything sequential, such as a tuple, a dictionary, a range object, or maybe things we haven't even considered. I don't want to have to create if... raise statements for every possible kind of input my function could take, right?\n",
- "\n",
- "This is where try comes in, and the mantra that \"It's easier to ask forgiveness than permission\". In short, try does what it says on the tin: it tries to do something! The difference is that we can provide further instructions in case what it is trying to do goes wrong. This would be more appropriate:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {
- "scrolled": true
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "S\n",
- "a\n",
- "m\n"
- ]
- }
- ],
- "source": [
- "try:\n",
- " acts_on_a_list(letters)\n",
- "except TypeError:\n",
- " print(\"acts_on_a_list was not provided with a sequence!\")\n",
- " "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "acts_on_a_list was not provided with a sequence!\n"
- ]
- }
- ],
- "source": [
- "try:\n",
- " acts_on_a_list(42)\n",
- "except TypeError:\n",
- " print(\"acts_on_a_list was not provided with a sequence!\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "So this one didn't actually cause the error message. Instead, the exception was \"caught\" before the error message occurred, and a new bit of code was executed to say what happens next. This could be, for instance, performing an alternative version of the action:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "acts_on_a_list was not provided with a sequence!\n",
- "E\n",
- "x\n",
- "a\n",
- "m\n",
- "p\n",
- "l\n",
- "e\n"
- ]
- }
- ],
- "source": [
- "try:\n",
- " acts_on_a_list(42)\n",
- "except TypeError:\n",
- " print(\"acts_on_a_list was not provided with a sequence!\")\n",
- " acts_on_a_list(\"Example\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Notice, we have precisely specified what kind of error we wish to catch: other kinds of errors will still occur in the usual way."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "ename": "IndexError",
- "evalue": "list index out of range",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0macts_on_a_list\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"HiPy\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"Sam\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"acts_on_a_list was not provided with a sequence!\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0macts_on_a_list\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Example\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;31mIndexError\u001b[0m: list index out of range"
- ]
- }
- ],
- "source": [
- "try:\n",
- " acts_on_a_list([\"HiPy\", \"Sam\"][3])\n",
- "except TypeError:\n",
- " print(\"acts_on_a_list was not provided with a sequence!\")\n",
- " acts_on_a_list(\"Example\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This is a good thing -- remember, we usually only want to catch the expected errors, and still be alerted properly if something truly unexpected happens. It's possible to use pass to continue as if nothing happened"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Look, nothing happened\n"
- ]
- }
- ],
- "source": [
- "try:\n",
- " acts_on_a_list(3.14)\n",
- "except TypeError:\n",
- " pass\n",
- "print(\"Look, nothing happened\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "And it seems like nothing happened. If we use except without providing the name of an exception, all exceptions will be handled in the same way (or ignored, if this is followed by pass). This is occasionally useful, but only if you know what you're doing -- specific, targeted errors are preferred. Here's a more practical little example of try, to add corresponding elements :"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "def add_list_elements(listA, listB):\n",
- " longest_list = max([listA, listB], key=len)\n",
- " listC = [x for x in longest_list]\n",
- " for i, value in enumerate(listC):\n",
- " try:\n",
- " listC[i] = listA[i] + listB[i]\n",
- " except IndexError:\n",
- " pass\n",
- " return listC"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "So we start by creating a copy of the longest list. Then for each index of the new list, we attempt to replace that list entry with the sum of the corresponding entries from the original of the two lists. If this fails due to an index error, which it eventually will if the lists are different sizes, we do nothing -- we just leave it as the same entry as the longer list:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[15, 25, 3, 123, 4]\n"
- ]
- }
- ],
- "source": [
- "A = [5, 5, 3, 123, 4]\n",
- "B = [10, 20]\n",
- "print(add_list_elements(A,B))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You can respond to different exceptions by giving them in sequence, as in:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "try:\n",
- " something()\n",
- "except Exception1:\n",
- " do_this()\n",
- "except Exception2:\n",
- " do_that()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "try...except can be followed with an else clause, which occurs only if there was no exception.\n",
- "\n",
- "A final part can be added after a try...except block. This is finally. This is a piece of code that will run regardless of success, failure, caught or uncaught exceptions. It will run no matter what, even if the rest of your program comes crashing down.\n",
- "\n",
- "This is not unfamiliar -- it is precisely what with open() does when you open a file: it has a procedure for closing the file regardless of what happens while the file is open.\n",
- "\n",
- "As an example of a good time to raise an exception, recall the polynomial class we made in tutorial 10. Virtually nothing will work if the argument provided is not a sequence of numbers, so we might want to add a check:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "class Polynomial(list):\n",
- " def __init__(self, *coeffs):\n",
- " from collections.abc import Sequence\n",
- " from numbers import Number\n",
- " if isinstance(coeffs[0], Sequence):\n",
- " coeffs = coeffs[0]\n",
- " if not isinstance(coeffs, Sequence):\n",
- " raise TypeError(\"Argument should be a sequence of numbers\")\n",
- " for x in coeffs:\n",
- " if not isinstance(x, Number):\n",
- " raise TypeError(\"Argument should be a sequence of numbers\")\n",
- " \n",
- " coeffs = list(coeffs)\n",
- " list.__init__(coeffs)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [
- {
- "ename": "TypeError",
- "evalue": "Argument should be a sequence of numbers",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mPolynomial\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'a'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m5\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, *coeffs)\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mx\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mcoeffs\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mNumber\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 11\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Argument should be a sequence of numbers\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 12\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0mcoeffs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcoeffs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;31mTypeError\u001b[0m: Argument should be a sequence of numbers"
- ]
- }
- ],
- "source": [
- "Polynomial([3, 'a', 5])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Debugging\n",
- "\n",
- "While we're on the subject of errors, we should talk a little bit about how to root out those bugs. One way that can be quite fruitful is simply heavy use of the print() function, telling Python to print various bits of informations as your program is running so you can spot where something has gone wrong. You can then \"comment out\" or delete the print() functions when you are done with them (and you probably should, since while printing might not seem like much it can slow a program down a surprising amount!).\n",
- "\n",
- "Python provides a module that allows you to walk through your program step by step to see how it is working. Just import the module pdb, and you can get started.\n",
- "\n",
- "Firstly, it's good not to have to debug your program from the start, but to choose a problematic part of the program to interrogate. Just add pdb.set_trace() before the bit of code you wish to examine.\n",
- "\n",
- "Now when you run your code, you can interact with it as it is executing using simple commands. The first to know is that q is quit.\n",
- "\n",
- "To advance through your program, you have two main options, step and next, which can be abbreviated as s or n. The difference is s will go \"inside\" a function on a line, but n will simply evaluate the function and move on to the next line. This distinction is not really clear from the names, so I like to imagine that s stands for \"sub-routine\", which is another word for \"function\" in computer programming. To skip ahead to the end of a function you are currently \"inside\", type r, which stands for return.\n",
- "\n",
- "So, great, we can move through the lines of our program step by step. But what does this really tell us? Well, the great thing is, we can actually run any line of code or print any variable while we're inside. To run a line of code (for instance, to change a variable manually to see what happens), just type that line in, or prefix the line with a ! if there is any risk of ambiguity. To print a variable inside the debugger, you can just type p variable_name, to save you typing print() every time. "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "### EXAMPLE VIDEO TO GO HERE"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.1"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/PurePy 12. Parallel Computing/.ipynb_checkpoints/12.0 Parallel Computing-checkpoint.ipynb b/PurePy 12. Parallel Computing/.ipynb_checkpoints/12.0 Parallel Computing-checkpoint.ipynb
deleted file mode 100644
index 2fd6442..0000000
--- a/PurePy 12. Parallel Computing/.ipynb_checkpoints/12.0 Parallel Computing-checkpoint.ipynb
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "cells": [],
- "metadata": {},
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/PurePy 2. Logic and Flow/.ipynb_checkpoints/2.0 Logic and Flow-checkpoint.ipynb b/PurePy 2. Logic and Flow/.ipynb_checkpoints/2.0 Logic and Flow-checkpoint.ipynb
deleted file mode 100644
index 82339db..0000000
--- a/PurePy 2. Logic and Flow/.ipynb_checkpoints/2.0 Logic and Flow-checkpoint.ipynb
+++ /dev/null
@@ -1,894 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- ""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Logic and flow control\n",
- "\n",
- "When programming, it is rare that our programs are so simple that they are merely a list of instructions. Often, we are required to perform an operation several times (with slight modification), or make a decision as to whether to perform one operation or another. These require the related notions of logic, and flow control.\n",
- "\n",
- "## Booleans\n",
- "\n",
- "So far we have met numbers, and briefly strings, as basic types of data in Python. We now introduce the so-called boolean types, named for the English mathematician George Boole. These are the basic atoms of logical reasoning: the condition of being True or False."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "this_is_true = True\n",
- "this_is_false = False"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Pay close attention. These capitalized True and False words are neither strings, nor variables. They are examples of the special keywords that Python form part of the Python language, which we are not allowed to use as variables.\n",
- "\n",
- "Of course, we do not want to have to manually assign things to being True or False. We wish to have the computer do it for us! This is where logical expressions come in. If mathematical expressions evaluate to a number, then logical expressions evaluate to a boolean.\n",
- "\n",
- "Firstly, operations with booleans. There are 3 basic operations we can use to combine booleans to give a new boolean. The simplest, is \"not\". Applying the \"not\" operation to a boolean reverses its value:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(not True)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(not not True)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(not False)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(not(False)) # you can use brackets in boolean expressions\n",
- " #like in mathematical expressions,\n",
- " # to make them easier to read"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The next operation is called \"or\". \"Or\" takes two booleans, and is considered True if either of its input booleans are True. You can think of it as \"one, the other, or both\"."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(True or False)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(True or True)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(False or False)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The final operation is \"and\". \"And\" is considered True only if both inputs are True:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(True and True)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(True and False)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(False and False)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Note that and, or, not are all keywords.\n",
- "\n",
- "Now, this may seem all very abstract. The real use of these logical operations is that the inputs can be replaced by other logical expressions, which are evaluated before being fed into the logical operation. Most of these other logical expressions will be comparisons between objects. Suppose I am writing a quiz application. When the player gives an answer, I must make a comparison between the answer they give, and the correct answer, to decide whether or not they score a point. Two simple kinds of comparison are the greater than/less than comparisons between numbers: "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "x = 5\n",
- "print(x < 6)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(x < 3)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(x > 2 and x < 7)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(x < 1 or x < 9)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(x >= 6) # greater than or equal!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To make a direct comparison for equality, we use a double equals ==, to distinguish it from the variable assignment symbol =:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 17,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(x == 5)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To check whether two things are not equal, use !="
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(x != 5)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You can use the modulo (\"remainder\") operator to check whether a number is, say, even:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 19,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(x % 2 == 0) # no remainder when divided by 2 means it is even"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You may be surprised to find it is possible to compare lots of things, not just numbers. For example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 20,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(\"cat\" < \"dog\") # because cat comes first in the dictionary!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 21,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(\"cat\" != \"Cat\") # capitals matter!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now that we are thoroughly bored of booleans, let's put them to work by using them to control our code.\n",
- "\n",
- "## if-statements\n",
- "\n",
- "Now we start programming proper. Using if-statements, we can tell our program to do something only if a particular expression is True. For example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 22,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "What is the capital of France? Paris\n",
- "Correct!\n"
- ]
- }
- ],
- "source": [
- "answer = input(\"What is the capital of France? \")\n",
- "if answer == \"Paris\" or answer == \"paris\":\n",
- " print(\"Correct!\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The key part for us, of course, is the second and third line. Firstly, the second line. It's what is called an if-statement, and it announces its arrival with the keyword \"if\". Following \"if\" is a boolean expression, of the kind we have looked at above. Finally, there is a colon.\n",
- "\n",
- "A colon at the end of a line in Python announces that we are starting a new block of code, and the line is called the header of the block. In the case of the if-statement, the block is all the code that should be executed, should the if statement evaluate to True. Following every header, the next line should be indented by 4 spaces. The use of indentation is quite perculiar to Python; other languages tend to use curly braces to denote code blocks.\n",
- "\n",
- "Every line following the if-statement that is indented will be executed only if the boolean expression comes out True. To end the code block, and resume the normal flow of the program, begin a line without indentation. Example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 23,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Can confirm that 5 is greater than 3,\n",
- "Please carry on with your day\n",
- "\n",
- "The if-statement has ended now\n",
- "\n",
- "The second if-statement has ended now\n"
- ]
- }
- ],
- "source": [
- "if 5 > 3:\n",
- " print(\"Can confirm that 5 is greater than 3,\")\n",
- " print(\"Please carry on with your day\")\n",
- "\n",
- "print(\"\")\n",
- "print(\"The if-statement has ended now\")\n",
- "print(\"\")\n",
- "\n",
- "if 2 > 3:\n",
- " print(\"It seems that mathematics has ceased to function, as 2 is now greater than 3,\")\n",
- " print(\"If you are seeing this output, be very alarmed\")\n",
- " \n",
- "print(\"The second if-statement has ended now\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "From now on, we will be encountering indentation a lot. The structure of a Python program is expressed using indentation, and the Python interpreter can be very picky about correct indentation. So pay attention: always indent after a header!\n",
- "\n",
- "Now, it seems reasonable that if we wish to execute some code if something is True, there should be an option to do something only if it fails to be True. For this, we turn to else."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 24,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "What is the capital of France? Moscow\n",
- "Incorrect\n"
- ]
- }
- ],
- "source": [
- "answer = input(\"What is the capital of France? \")\n",
- "if answer == \"Paris\" or answer == \"paris\":\n",
- " print(\"Correct!\")\n",
- "else:\n",
- " print(\"Incorrect\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Hence, an if-else statement is like a fork in the road for the program. Now, if we want to set lots of little forks in the road, it might be tempting to do this:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 25,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "What is the capital of France? F\n",
- "Very Funny\n"
- ]
- }
- ],
- "source": [
- "answer = input(\"What is the capital of France? \")\n",
- "if answer == \"Paris\" or answer == \"paris\":\n",
- " print(\"Correct!\")\n",
- "else:\n",
- " if answer == \"F\":\n",
- " print(\"Very Funny\")\n",
- " else:\n",
- " print(\"Incorrect!\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Read this example to ensure that you understand it, and then forget about it. Python has a neater solution, rolling the else: if... part into a single line:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 26,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "What is the capital of France? F\n",
- "Very Funny\n"
- ]
- }
- ],
- "source": [
- "answer = input(\"What is the capital of France? \")\n",
- "if answer == \"Paris\" or answer == \"paris\":\n",
- " print(\"Correct!\")\n",
- "elif answer == \"F\": # elif is short for \"else, if\"\n",
- " print(\"Very Funny\")\n",
- "else:\n",
- " print(\"Incorrect!\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "In this way, you can set a whole chain of conditions to check for before doing the else block. That's pretty much all there is to if-statements. It is worth bearing in mind, however, that if your program is becoming a tangled mess of if, elif, else, with varying layers of depth of indentation, it's probably time to rethink your design. For example, we will soon meet a structure called a dictionary, which would allow us to store the possible answers to the quiz question alongside their responses from the program in a table."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Flow control: for-loops\n",
- "\n",
- "There are two kinds of loop in Python. A loop is a section of code that is repeated several times, usually with some variation.\n",
- "\n",
- "A for-loop is a loop that completes a task a certain number of times. In most programming languages, you simply specify \"do this 10 times\". In Python, you must \"iterate over\" something. Precisely what that means will be discussed in the more advanced articles. However, the intuition is straightforward enough: we specify some kind of sequence, and perform a task for each term in the sequence.\n",
- "\n",
- "Here is an example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 27,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "H\n",
- "e\n",
- "l\n",
- "l\n",
- "o\n",
- " \n",
- "w\n",
- "o\n",
- "r\n",
- "l\n",
- "d\n",
- "!\n"
- ]
- }
- ],
- "source": [
- "for letter in \"Hello world!\":\n",
- " print(letter)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Let's unpack it. Again, we have that pattern of keyword -- this time \"for\" -- followed by a statement and ending in a colon, all followed by an indented block. The indented block is the section of code that is to be repeated.\n",
- "\n",
- "Now, \"Hello world!\" is acting as the sequence -- it is a sequence of characters. What about a list of words?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 28,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Hello\n",
- "World\n"
- ]
- }
- ],
- "source": [
- "for word in [\"Hello\", \"World\"]:\n",
- " print(word)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The sequence here is a list, denoted by square braces (we'll see much more of lists in tutorials to come!). In the last two examples, \"letter\" and \"word\" are temporary variables we assign to each member of the list as we iterate through it. They can be anything -- letter and word were just chosen here to be clear and readable.\n",
- "\n",
- "The design philosophy here is that, when programming, if we want to do a task over and over again, we probably want to take a collection of data, such as a list, and perform an operation on each piece of data. That is what this is all about.\n",
- "\n",
- "Now, what if we really do want to do something 10 times, rather than work our way through a word or list? Then we have a function called range() which generates a sequences of numbers for us. Want to do something 10 times?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 29,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n"
- ]
- }
- ],
- "source": [
- "for x in range(10):\n",
- " print(\"Spam\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Note, we still had to specify a dummy variable x, but we didn't have to mention it in the code block. We just performed the task for each element of the sequence provided by the range() function which is"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 30,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "0\n",
- "1\n",
- "2\n",
- "3\n",
- "4\n",
- "5\n",
- "6\n",
- "7\n",
- "8\n",
- "9\n"
- ]
- }
- ],
- "source": [
- "for x in range(10):\n",
- " print(x)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## While-loops\n",
- "\n",
- "The other kind of loop we have at our disposal is called a while-loop. Instead of doing something a fixed number of times, the while-loop executes its contents until some condition is met. This makes them work a lot like if statements, since we are checking whether a certain logical expression evaluates to True, or False.\n",
- "\n",
- "While-loops come with a word of warning. Prudence is required when programming the loop. If the condition is never met, then the program may continue to execute forever, until it is halted by outside forces, such as an interrupt message from the keyboard (usually ctrl+c), or the computer freezes because the computations it is performing have got out of hand.\n",
- "\n",
- "As a familiar real-world example, a computer game is nothing else but a while-loop. The loop consists of getting input from the player via the keyboard or joypad, updating the game state, and then drawing the results on the screen. This loop is repeated possibly hundreds of times per second in the case of real-time games, or at the leisure of the player in turn-based games. The loop halts when the player wins, loses, or quits the game.\n",
- "\n",
- "The first example we will see for a while-loop is one that emulates a for-loop. In this case, a certain counter is started, and that counter is incremented each time the looping block is executed. When the counter reaches a certain point, the loop stops.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 31,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n"
- ]
- }
- ],
- "source": [
- "counter = 0\n",
- "while counter < 10:\n",
- " print(\"Spam\")\n",
- " counter = counter + 1 # increment the counter"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Of course, there is not much point in doing this. However, counters remain useful if they only increment under specific conditions, which requires use of an if-statement to decide when to increment the counter."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## The fizzbuzz challenge\n",
- "\n",
- "This is a classic programming exercise, appearing in many courses and even job interviews. The task is simple, but if you can solve it, you know you've got the hang of logic and flow control. Your task is to write a short program that prints out the numbers 1 to 100, but if the number is divisible by 3, to print \"Fizz\" instead; and if it is divisible by 5, print \"Buzz\"; and if it is divisible by both 3 and 5, print \"Fizzbuzz\". Everything you need to solve this challenge is contained in the above text, but you will need to design an algorithm that successfully combines these elements to produce the correct solution.\n",
- "\n",
- "Have a good go, but if you get stuck, see the video below for a solution:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 32,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "image/jpeg": "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\n",
- "text/html": [
- "\n",
- " \n",
- " "
- ],
- "text/plain": [
- ""
- ]
- },
- "execution_count": 32,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "from IPython.display import YouTubeVideo\n",
- "YouTubeVideo(\"CzPpVurUSIM\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.5.2"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 1
-}
diff --git a/PurePy 2. Logic and Flow/.ipynb_checkpoints/logic and flow-checkpoint.ipynb b/PurePy 2. Logic and Flow/.ipynb_checkpoints/logic and flow-checkpoint.ipynb
deleted file mode 100644
index cf5b1a3..0000000
--- a/PurePy 2. Logic and Flow/.ipynb_checkpoints/logic and flow-checkpoint.ipynb
+++ /dev/null
@@ -1,898 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- ""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Logic and flow control\n",
- "\n",
- "When programming, it is rare that our programs are so simple that they are merely a list of instructions. Often, we are required to perform an operation several times (with slight modification), or make a decision as to whether to perform one operation or another. These require the related notions of logic, and flow control.\n",
- "\n",
- "## Booleans\n",
- "\n",
- "So far we have met numbers, and briefly strings, as basic types of data in Python. We now introduce the so-called boolean types, named for the English mathematician George Boole. These are the basic atoms of logical reasoning: the condition of being True or False."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "this_is_true = True\n",
- "this_is_false = False"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Pay close attention. These capitalized True and False words are neither strings, nor variables. They are examples of the special keywords that Python form part of the Python language, which we are not allowed to use as variables.\n",
- "\n",
- "Of course, we do not want to have to manually assign things to being True or False. We wish to have the computer do it for us! This is where logical expressions come in. If mathematical expressions evaluate to a number, then logical expressions evaluate to a boolean.\n",
- "\n",
- "Firstly, operations with booleans. There are 3 basic operations we can use to combine booleans to give a new boolean. The simplest, is \"not\". Applying the \"not\" operation to a boolean reverses its value:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(not True)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(not not True)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(not False)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(not(False)) # you can use brackets in boolean expressions\n",
- " #like in mathematical expressions,\n",
- " # to make them easier to read"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The next operation is called \"or\". \"Or\" takes two booleans, and is considered True if either of its input booleans are True. You can think of it as \"one, the other, or both\"."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(True or False)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(True or True)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(False or False)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The final operation is \"and\". \"And\" is considered True only if both inputs are True:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(True and True)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(True and False)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(False and False)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Note that and, or, not are all keywords.\n",
- "\n",
- "Now, this may seem all very abstract. The real use of these logical operations is that the inputs can be replaced by other logical expressions, which are evaluated before being fed into the logical operation. Most of these other logical expressions will be comparisons between objects. Suppose I am writing a quiz application. When the player gives an answer, I must make a comparison between the answer they give, and the correct answer, to decide whether or not they score a point. Two simple kinds of comparison are the greater than/less than comparisons between numbers: "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 46,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "x = 5\n",
- "print(x < 6)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 47,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(x < 3)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 48,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(x > 2 and x < 7)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 49,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(x < 1 or x < 9)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 50,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(x >= 6) # greater than or equal!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To make a direct comparison for equality, we use a double equals ==, to distinguish it from the variable assignment symbol =:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 51,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(x == 5)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To check whether two things are not equal, use !="
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 52,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(x != 5)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You can use the modulo (\"remainder\") operator to check whether a number is, say, even:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [
- {
- "ename": "NameError",
- "evalue": "name 'x' is not defined",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0;36m2\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# no remainder when divided by 2 means it is even\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;31mNameError\u001b[0m: name 'x' is not defined"
- ]
- }
- ],
- "source": [
- "print(x % 2 == 0) # no remainder when divided by 2 means it is even"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You may be surprised to find it is possible to compare lots of things, not just numbers. For example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 19,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(\"cat\" < \"dog\") # because cat comes first in the dictionary!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 20,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(\"cat\" != \"Cat\") # capitals matter!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now that we are thoroughly bored of booleans, let's put them to work by using them to control our code.\n",
- "\n",
- "## if-statements\n",
- "\n",
- "Now we start programming proper. Using if-statements, we can tell our program to do something only if a particular expression is True. For example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 26,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "What is the capital of France? Paris\n",
- "Correct!\n"
- ]
- }
- ],
- "source": [
- "answer = input(\"What is the capital of France? \")\n",
- "if answer == \"Paris\" or answer == \"paris\":\n",
- " print(\"Correct!\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The key part for us, of course, is the second and third line. Firstly, the second line. It's what is called an if-statement, and it announces its arrival with the keyword \"if\". Following \"if\" is a boolean expression, of the kind we have looked at above. Finally, there is a colon.\n",
- "\n",
- "A colon at the end of a line in Python announces that we are starting a new block of code, and the line is called the header of the block. In the case of the if-statement, the block is all the code that should be executed, should the if statement evaluate to True. Following every header, the next line should be indented by 4 spaces. The use of indentation is quite perculiar to Python; other languages tend to use curly braces to denote code blocks.\n",
- "\n",
- "Every line following the if-statement that is indented will be executed only if the boolean expression comes out True. To end the code block, and resume the normal flow of the program, begin a line without indentation. Example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Can confirm that 5 is greater than 3,\n",
- "Please carry on with your day\n",
- "\n",
- "The if-statement has ended now\n",
- "\n",
- "The second if-statement has ended now\n"
- ]
- }
- ],
- "source": [
- "if 5 > 3:\n",
- " print(\"Can confirm that 5 is greater than 3,\")\n",
- " print(\"Please carry on with your day\")\n",
- "\n",
- "print(\"\")\n",
- "print(\"The if-statement has ended now\")\n",
- "print(\"\")\n",
- "\n",
- "if 2 > 3:\n",
- " print(\"It seems that mathematics has ceased to function, as 2 is now greater than 3,\")\n",
- " print(\"If you are seeing this output, be very alarmed\")\n",
- " \n",
- "print(\"The second if-statement has ended now\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "From now on, we will be encountering indentation a lot. The structure of a Python program is expressed using indentation, and the Python interpreter can be very picky about correct indentation. So pay attention: always indent after a header!\n",
- "\n",
- "Now, it seems reasonable that if we wish to execute some code if something is True, there should be an option to do something only if it fails to be True. For this, we turn to else."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 31,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "What is the capital of France? Moscow\n",
- "Incorrect\n"
- ]
- }
- ],
- "source": [
- "answer = input(\"What is the capital of France? \")\n",
- "if answer == \"Paris\" or answer == \"paris\":\n",
- " print(\"Correct!\")\n",
- "else:\n",
- " print(\"Incorrect\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Hence, an if-else statement is like a fork in the road for the program. Now, if we want to set lots of little forks in the road, it might be tempting to do this:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 32,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "What is the capital of France? F\n",
- "Very Funny\n"
- ]
- }
- ],
- "source": [
- "answer = input(\"What is the capital of France? \")\n",
- "if answer == \"Paris\" or answer == \"paris\":\n",
- " print(\"Correct!\")\n",
- "else:\n",
- " if answer == \"F\":\n",
- " print(\"Very Funny\")\n",
- " else:\n",
- " print(\"Incorrect!\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Read this example to ensure that you understand it, and then forget about it. Python has a neater solution, rolling the else: if... part into a single line:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 33,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "What is the capital of France? London\n",
- "Incorrect!\n"
- ]
- }
- ],
- "source": [
- "answer = input(\"What is the capital of France? \")\n",
- "if answer == \"Paris\" or answer == \"paris\":\n",
- " print(\"Correct!\")\n",
- "elif answer == \"F\": # elif is short for \"else, if\"\n",
- " print(\"Very Funny\")\n",
- "else:\n",
- " print(\"Incorrect!\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "In this way, you can set a whole chain of conditions to check for before doing the else block. That's pretty much all there is to if-statements. It is worth bearing in mind, however, that if your program is becoming a tangled mess of if, elif, else, with varying layers of depth of indentation, it's probably time to rethink your design. For example, we will soon meet a structure called a dictionary, which would allow us to store the possible answers to the quiz question alongside their responses from the program in a table."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Flow control: for-loops\n",
- "\n",
- "There are two kinds of loop in Python. A loop is a section of code that is repeated several times, usually with some variation.\n",
- "\n",
- "A for-loop is a loop that completes a task a certain number of times. In most programming languages, you simply specify \"do this 10 times\". In Python, you must \"iterate over\" something. Precisely what that means will be discussed in the more advanced articles. However, the intuition is straightforward enough: we specify some kind of sequence, and perform a task for each term in the sequence.\n",
- "\n",
- "Here is an example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 34,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "H\n",
- "e\n",
- "l\n",
- "l\n",
- "o\n",
- " \n",
- "w\n",
- "o\n",
- "r\n",
- "l\n",
- "d\n",
- "!\n"
- ]
- }
- ],
- "source": [
- "for letter in \"Hello world!\":\n",
- " print(letter)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Let's unpack it. Again, we have that pattern of keyword -- this time \"for\" -- followed by a statement and ending in a colon, all followed by an indented block. The indented block is the section of code that is to be repeated.\n",
- "\n",
- "Now, \"Hello world!\" is acting as the sequence -- it is a sequence of characters. What about a list of words?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 35,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Hello\n",
- "World\n"
- ]
- }
- ],
- "source": [
- "for word in [\"Hello\", \"World\"]:\n",
- " print(word)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The sequence here is a list, denoted by square braces (we'll see much more of lists in tutorials to come!). In the last two examples, \"letter\" and \"word\" are temporary variables we assign to each member of the list as we iterate through it. They can be anything -- letter and word were just chosen here to be clear and readable.\n",
- "\n",
- "The design philosophy here is that, when programming, if we want to do a task over and over again, we probably want to take a collection of data, such as a list, and perform an operation on each piece of data. That is what this is all about.\n",
- "\n",
- "Now, what if we really do want to do something 10 times, rather than work our way through a word or list? Then we have a function called range() which generates a sequences of numbers for us. Want to do something 10 times?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 36,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n"
- ]
- }
- ],
- "source": [
- "for x in range(10):\n",
- " print(\"Spam\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Note, we still had to specify a dummy variable x, but we didn't have to mention it in the code block. We just performed the task for each element of the sequence provided by the range() function which is"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 37,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "0\n",
- "1\n",
- "2\n",
- "3\n",
- "4\n",
- "5\n",
- "6\n",
- "7\n",
- "8\n",
- "9\n"
- ]
- }
- ],
- "source": [
- "for x in range(10):\n",
- " print(x)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## While-loops\n",
- "\n",
- "The other kind of loop we have at our disposal is called a while-loop. Instead of doing something a fixed number of times, the while-loop executes its contents until some condition is met. This makes them work a lot like if statements, since we are checking whether a certain logical expression evaluates to True, or False.\n",
- "\n",
- "While-loops come with a word of warning. Prudence is required when programming the loop. If the condition is never met, then the program may continue to execute forever, until it is halted by outside forces, such as an interrupt message from the keyboard (usually ctrl+c), or the computer freezes because the computations it is performing have got out of hand.\n",
- "\n",
- "As a familiar real-world example, a computer game is nothing else but a while-loop. The loop consists of getting input from the player via the keyboard or joypad, updating the game state, and then drawing the results on the screen. This loop is repeated possibly hundreds of times per second in the case of real-time games, or at the leisure of the player in turn-based games. The loop halts when the player wins, loses, or quits the game.\n",
- "\n",
- "The first example we will see for a while-loop is one that emulates a for-loop. In this case, a certain counter is started, and that counter is incremented each time the looping block is executed. When the counter reaches a certain point, the loop stops.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 39,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n",
- "Spam\n"
- ]
- }
- ],
- "source": [
- "counter = 0\n",
- "while counter < 10:\n",
- " print(\"Spam\")\n",
- " counter = counter + 1 # increment the counter"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Of course, there is not much point in doing this. However, counters remain useful if they only increment under specific conditions, which requires use of an if-statement to decide when to increment the counter."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## The fizzbuzz challenge\n",
- "\n",
- "This is a classic programming exercise, appearing in many courses and even job interviews. The task is simple, but if you can solve it, you know you've got the hang of logic and flow control. Your task is to write a short program that prints out the numbers 1 to 100, but if the number is divisible by 3, to print \"Fizz\" instead; and if it is divisible by 5, print \"Buzz\"; and if it is divisible by both 3 and 5, print \"Fizzbuzz\". Everything you need to solve this challenge is contained in the above text, but you will need to design an algorithm that successfully combines these elements to produce the correct solution.\n",
- "\n",
- "Have a good go, but if you get stuck, see the video below for a solution:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 54,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "image/jpeg": "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\n",
- "text/html": [
- "\n",
- " \n",
- " "
- ],
- "text/plain": [
- ""
- ]
- },
- "execution_count": 54,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "from IPython.display import YouTubeVideo\n",
- "YouTubeVideo(\"CzPpVurUSIM\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.5.2"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 1
-}
diff --git a/PurePy 3. Importing modules/.ipynb_checkpoints/Importing more functions-checkpoint.ipynb b/PurePy 3. Importing modules/.ipynb_checkpoints/Importing more functions-checkpoint.ipynb
deleted file mode 100644
index e95d2b3..0000000
--- a/PurePy 3. Importing modules/.ipynb_checkpoints/Importing more functions-checkpoint.ipynb
+++ /dev/null
@@ -1,275 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Importing More Functions\n",
- "\n",
- "We have been using just a small handful of functions so far. For our present purposes, a function is a command that takes some inputs, called arguments, and returns an output (this definition will be expanded in the next guide). The function \"evaluates\" to whatever it returns as its output, in the same way that a mathematical expression evaluates to a number, and boolean expression evaluates to True or False. Executing a function is called calling the function. We always know that a function is being called if there is a word followed by opening and closing brackets, which contain the inputs to the function. For example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "323\n"
- ]
- }
- ],
- "source": [
- "a = max(1, 323, 3)\n",
- "print(a) # max and print are both functions! the max() function evaluated to 323."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "At time of writing, Python has 68 built-in functions which you can read about here https://docs.python.org/3/library/functions.html. There is no need to memorize this list. As you complete common tasks, your memory for the most useful built-in functions will grow.\n",
- "\n",
- "There are far more functions available than just these that are built-in. A library is a collection of code that is designed to be used in other programs, to improve the functionality of that program without the programmer having to do it all from scratch. Most programming languages have a \"standard library\", included wherever basic software (such as the interpreter) is installed, and Python is no exception. You can also create your own libraries, and use libraries not included in the standard library. If you installed Python using Anaconda, you will already have access to a large collection of non-standard libraries.\n",
- "\n",
- "Making use of a library takes the form of importing a module. A module is just a file containing Python code, and the syntax for doing this is easy. Let's import a module from the standard library. Suppose we wish to get some basic statistical facts about a set of data points."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "import statistics"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "That's all there is to it. When a module is imported, the code contained in that module is executed, and any functions, variables, or other objects it provides are loaded into the memory. To access them, we use the dot operator in the following way: modulename.thingwewant. For example, we wish to find the mean in the following data set:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "96.2200289611252\n"
- ]
- }
- ],
- "source": [
- "datapoints = [122.4405632654331, 115.75254005489799, 92.53967075824983, 103.53590194401652, 81.27219333775719, 101.61965193699073, 78.30111045299329, 114.11585074905481, 114.76222147968035, 94.74755847301873, 125.01631527683821, 105.17195190259096, 128.33700175849353, 89.38673085168398, 90.40490836715898, 74.35979914723771, 78.9020965751661, 71.23417050705106, 63.745428686885354, 78.75491369730545]\n",
- "\n",
- "average = statistics.mean(datapoints)\n",
- "print(average)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "If we anticipate that we will be using the statistics module a lot, we might want to give it a nickname for ease of typing:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "93.64361461563428\n"
- ]
- }
- ],
- "source": [
- "import statistics as stats\n",
- "med = stats.median(datapoints)\n",
- "print(med)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "If it is just the case that we want only a small number of the functions provided by a module, we can import just that function. In this case, we no longer have to specify the module that function has been imported from:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "376.7948073834579\n"
- ]
- }
- ],
- "source": [
- "from statistics import variance\n",
- "var = variance(datapoints) # didn't need to write stats.variance\n",
- "print(var)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The Python standard library is large and impressive. Most common tasks computing tasks are aided by standard library modules, such as downloading information from the internet, performing common mathematical operations, reading certain kinds of file from your computer, and so on. You can read about every module available in the standard library in this intimidating list here https://docs.python.org/3/library/."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": true
- },
- "source": [
- "## Where does Python import the modules from?\n",
- "\n",
- "This depends on your Python installation and operating system. With a standard Python installation on a UNIX-like (Mac or Linux) system, there is an environment variable called $PYTHONPATH. On different operating systems, or with an Anaconda installation, this might differ (I think Anaconda just looks inside its own directory although I could be mistaken about this, the documentation isn't clear).\n",
- "\n",
- "Two places that Python always looks is the current working directory, and the location where the script itself is saved. Recall from the command-line article/video that the user always has a current working directory when navigating using the shell. Whenever Python is running, it also has a current working directory (by default the working directory of the shell from which the script was launched)."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Splitting up projects into many files\n",
- "\n",
- "The other key use of the import command is to allow your work to be spread over multiple files, which can all be brought together by importing them into a \"main\" file. This is essential for making large projects more manageable, as different aspects of the program can be handled independently.\n",
- "\n",
- "As an amusing anecdote and warning, Mark R Johnson, the sole developer of a game in-progress called Ultima Ratio Regum, had never written a line of code in his life when he started development. The game is staggeringly complex as a first programming project, and happens to be written in Python. While he clearly learned a lot of programming along the way, he missed the tip that programmers tend to split up their code across several files, as well as keeping data files (information the code works on) separated from program files (the actual code). At one point he admitted he was now working from a single Python file several hundred thousand lines long and that as well as being unmanageable from a human psychology perspective was causing his text editor to crash frequently under the strain of such a large file.\n",
- "\n",
- "So don't be like Mark. If you have to write a large program, split the main parts of the problem up into different files and code them separately. Then import them into a main file. Also, consider if any parts of the program you are writing could be useful in a future program! Then you can put them into one file and just import that file as and when needed in other programs."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": true
- },
- "source": [
- "## Modules that can act as libraries or stand-alone programs\n",
- "\n",
- "There is a useful line of Python that can be used when writing a Python file, to give it a different behaviour if it is run as a stand-alone program, or if it is imported as a module.\n",
- "\n",
- "As an example, let's suppose I am a physics student who wants to write a very simple module that acts in two possible ways. The module provides some physical constants: if I import the module, I gain access to those physical constants in my other program. Alternatively, if I run the module by itself, say, from the command line, it prints out a list of all the physical constants defined therein.\n",
- "\n",
- "Here is the example code:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "# these constants are available if the module is imported\n",
- "speed_of_light = 299792458\n",
- "planck = 6.62607004e-34\n",
- "electron_charge = -1.6021766208e-19\n",
- "electron_mass = 9.10938356e-31\n",
- "\n",
- "if __name__ == '__main__':\n",
- " # this code will ONLY be executed if the module\n",
- " # is launched independently, not imported.\n",
- " print(\"The speed of light in a vacuum is\", speed_of_light, \"ms⁻ⁱ\")\n",
- " print(\"Planck's constant is\", planck, \"J·s\")\n",
- " print(\"An electron has charge\", electron_charge, \"C\")\n",
- " print(\"An electron has mass\", electron_mass, \"kg\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now if I save this as, say, constants.py, I can import it like so:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Electron rest energy = 8.187105649650028e-14 J\n"
- ]
- }
- ],
- "source": [
- "import constants\n",
- "\n",
- "print(\"Electron rest energy =\",\n",
- " constants.electron_mass * constants.speed_of_light**2, \"J\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "However, going to my command line and typing python constants.py displays:"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "$ python constants.py\n",
- "The speed of light in a vacuum is 299792458 ms⁻ⁱ\n",
- "Planck's constant is 6.62607004e-34 J·s\n",
- "An electron has charge -1.6021766208e-19 C\n",
- "An electron has mass 9.10938356e-31 kg\n",
- "$"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.1"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 1
-}
diff --git a/PurePy 4. Defining Our Own Functions/.ipynb_checkpoints/Defining our own functions-checkpoint.ipynb b/PurePy 4. Defining Our Own Functions/.ipynb_checkpoints/Defining our own functions-checkpoint.ipynb
deleted file mode 100644
index ea228e6..0000000
--- a/PurePy 4. Defining Our Own Functions/.ipynb_checkpoints/Defining our own functions-checkpoint.ipynb
+++ /dev/null
@@ -1,771 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Defining functions\n",
- "\n",
- "We have seen that there are many useful functions built-in to Python, and many more available sitting in the standard library and other modules just waiting to be imported to help us complete tasks. This is far from the end of the story though. We previous defined a function to be a command that takes an input argument, and returns an output. The real power of functions, however, is that we can create our own, making a piece of code that can be reused anywhere in our program, or imported into other programs.\n",
- "\n",
- "Remember, the key to programming is breaking down large complex tasks into small simple tasks. Functions are the key to doing this. They help us to organize and formalize this process by turning each small task into a separate function. These functions can then be reused and combined over and over. For this reason, you should virtually never have to copy and paste code to complete several similar tasks: the correct thing to do is create a function that completes these tasks, and use it several times.\n",
- "\n",
- "This leads to the concept computer scientists refer to as \"abstraction\". It means that already-solved problems can be essentially forgotten about, treated as single step in an algorithm, however complex that problem may have been initially. For example, if I am building a program that collects stock market data from the web, the simple act of making a webpage request is extraordinarily complex. My request travels in the form of electrical \"on/off\" (0/1) signals through the air to my home router, a computer which reads the metadata of my request and sends the request on a journey via dozens of other routers; to a server with the software to decode my 0s and 1s; which then gets the stock market data by some other magic; and then sends the data back to my computer's address, again via dozens of routers, each one figuring where to send the information next; finally decoded my home computer. The process is extremely complex. But it was solved by the original engineers of the internet and the hyper-text transfer protocol (HTTP) decades ago. To me, in my project, I just run pandas' web data reader function. It's all achieved in a single step. That is abstraction in a nutshell. Functions allow us to solve a complicated problem once, and then treat it as a single step thereafter.\n",
- "\n",
- "Once again, functions in the code are indicated by a header, followed by the correct indentation. The keyword for the header is def, for \"define\". The function then executes until it reaches the end of the indented text or, more importantly, until it reaches the return keyword, which tells the function what to output."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 38,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "def a_silly_function():\n",
- " # We are now defining a function\n",
- " print(\"This function does nothing\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Defining a function does nothing right away! We have to call it to make the magic happen."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 39,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "This function does nothing\n"
- ]
- }
- ],
- "source": [
- "a_silly_function() # a function is executed by typing its name followed by brackets."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The brackets to call the function are very important. If we refer to a function without the brackets, we are just referring to it, not \"activating\" it. For instance, we can set a function to a variable:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 52,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "silly = a_silly_function"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 53,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "This function does nothing\n"
- ]
- }
- ],
- "source": [
- "silly()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Parameters and arguments\n",
- "\n",
- "As mentioned, functions typically take one or more inputs, making them capable of being used in more situations. Inside the function definition, these inputs are given placeholder names, called parameters, which behave like temporary variables. The parameters are specified in the brackets in the header of the function:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "def says_a_phrase(phrase):\n",
- " print('\"' + phrase + ',\" said the computer')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The inputs given to each use of the function are called arguments. Each time the function is executed, the parameters in the function definition are substituted for the arguments provided when the function is called:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\"Hello,\" said the computer\n",
- "\"I think, therefore I am,\" said the computer\n",
- "\"But I cannot think, so perhaps I am not,\" said the computer\n"
- ]
- }
- ],
- "source": [
- "says_a_phrase(\"Hello\")\n",
- "says_a_phrase(\"I think, therefore I am\")\n",
- "says_a_phrase(\"But I cannot think, so perhaps I am not\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "In this example, phrase is the parameter, \"Hello\" and so on are the arguments.\n",
- "\n",
- "We can provide functions with multiple arguments. There are two ways of doing this: by position, and by keyword. Firstly, by position:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "def says_a_phrase_repeatedly(phrase, repeat):\n",
- " for x in range(repeat):\n",
- " says_a_phrase(phrase) # notice we are calling the previously defined function inside this function!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\"Error,\" said the computer\n",
- "\"Error,\" said the computer\n",
- "\"Error,\" said the computer\n",
- "\"Error,\" said the computer\n",
- "\"Error,\" said the computer\n"
- ]
- }
- ],
- "source": [
- "says_a_phrase_repeatedly(\"Error\", 5)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "In this case, the order of the arguments provided must match the order of the parameters in the definition if the function is to work correctly. The following will not work:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 17,
- "metadata": {},
- "outputs": [
- {
- "ename": "TypeError",
- "evalue": "'str' object cannot be interpreted as an integer",
- "output_type": "error",
- "traceback": [
- "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)",
- "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0msays_a_phrase_repeatedly\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m5\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"Error\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[1;32m\u001b[0m in \u001b[0;36msays_a_phrase_repeatedly\u001b[1;34m(phrase, repeat)\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0msays_a_phrase_repeatedly\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mphrase\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mrepeat\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[1;32mfor\u001b[0m \u001b[0mx\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mrepeat\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 3\u001b[0m \u001b[0msays_a_phrase\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mphrase\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;31m# notice we are calling the previously defined function inside this function!\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
- "\u001b[1;31mTypeError\u001b[0m: 'str' object cannot be interpreted as an integer"
- ]
- }
- ],
- "source": [
- "says_a_phrase_repeatedly(5, \"Error\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Positional arguments are useful when there is only a small number of arguments, and the order is easy to remember.\n",
- "\n",
- "The alternative is keyword arguments. We can use the keyword arguments like so:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\"0110111,\" said the computer\n",
- "\"0110111,\" said the computer\n",
- "\"0110111,\" said the computer\n",
- "\"0110111,\" said the computer\n",
- "\"0110111,\" said the computer\n"
- ]
- }
- ],
- "source": [
- "says_a_phrase_repeatedly(phrase=\"0110111\",repeat=5)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now the order doesn't matter:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 19,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\"0110111,\" said the computer\n",
- "\"0110111,\" said the computer\n",
- "\"0110111,\" said the computer\n"
- ]
- }
- ],
- "source": [
- "says_a_phrase_repeatedly(repeat=3,phrase=\"0110111\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This is very useful when there are several arguments to pass to a function, and it is not clear in what order these should come. It can also make the meaning of the code clearer when the function is being called. The two approaches of positional and keyword arguments can be combined, so long as we follow the rule that positional arguments come first, followed by keyword arguments."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Another useful aspect of keyword arguments is that they can have default values set in the function definition. If the keyword argument is omitted from the function call, the default value is used. This cannot be done with positional arguments, because omitting an argument in this case would change the position of all arguments that follow!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 34,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "def says_a_phrase_backwards(phrase, repeat=5):\n",
- " for i in range(repeat):\n",
- " says_a_phrase(phrase[::-1])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 35,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\"rorre suoireS,\" said the computer\n",
- "\"rorre suoireS,\" said the computer\n",
- "\"rorre suoireS,\" said the computer\n",
- "\"rorre suoireS,\" said the computer\n",
- "\"rorre suoireS,\" said the computer\n",
- "\"toobeR,\" said the computer\n",
- "\"toobeR,\" said the computer\n",
- "\"toobeR,\" said the computer\n"
- ]
- }
- ],
- "source": [
- "says_a_phrase_backwards(\"Serious error\") # uses default value for repeat\n",
- "says_a_phrase_backwards(\"Reboot\", repeat=3) # uses the provided value"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Scope\n",
- "\n",
- "A key advantage (and source of confusion for beginners) when using functions is the idea of scope of variables.\n",
- "\n",
- "We are quite used to assigning variables in the main body of our code. These are called global variables. A variable assigned inside of a function block is called a local variable. It has no meaning beyond the boundaries of the function. Once the function has completed its task, the variable is promptly forgotten about.\n",
- "\n",
- "While this does lead to mistakes and frustration early on, the benefits are roughly twofold. For starters, this means that the same variable name can be reused in different contexts -- we don't always have to come up with something new. Secondly, this makes it much less likely that functions will interfere with one another's inner workings. If functions could easily modify global variables, or the variables local to other functions, we would soon run in to errors. However, if each function is allowed to operate as a self-contained unit, this cannot happen. Example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 40,
- "metadata": {},
- "outputs": [
- {
- "ename": "NameError",
- "evalue": "name 'b' is not defined",
- "output_type": "error",
- "traceback": [
- "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)",
- "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 5\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 6\u001b[0m \u001b[0massigns_some_variables\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 7\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mb\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[1;31mNameError\u001b[0m: name 'b' is not defined"
- ]
- }
- ],
- "source": [
- "def assigns_some_variables():\n",
- " a = 1\n",
- " b = 2\n",
- " c = 3\n",
- "\n",
- "assigns_some_variables()\n",
- "print(b)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "If, for some reason, we do want a function to set a global variable, we can use the keyword global, like so"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 42,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "2\n"
- ]
- }
- ],
- "source": [
- "def assigns_some_variables():\n",
- " global a, b\n",
- " a = 1\n",
- " b = 2\n",
- " c = 3\n",
- "\n",
- "assigns_some_variables()\n",
- "print(b)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 43,
- "metadata": {},
- "outputs": [
- {
- "ename": "NameError",
- "evalue": "name 'c' is not defined",
- "output_type": "error",
- "traceback": [
- "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)",
- "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mc\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[1;31mNameError\u001b[0m: name 'c' is not defined"
- ]
- }
- ],
- "source": [
- "print(c)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "If you have to do this too often though, it's likely a sign that your design is flawed in some way. In most larger programs, only a few variables are truly necessary to be global; most variables we set are just stepping stones toward the main results, and should be kept local. You may often here the mantra \"no global variables\". For small scripts performing a single simple task, this is probably overkill, but it's worth bearing in mind for larger projects where conflict and interference between variables becomes more likely."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Returning an output\n",
- "\n",
- "So far, these functions haven't really given us an output. Rather, they've just been calling the print function, which displays some text to the screen but doesn't actually evaluate to anything, in the sense that a mathematical expression evaluates to a number, or a logical expression evaluates to a boolean.\n",
- "\n",
- "A return statement is a line in a function that tells the function to stop executing, and output a given value. One function can have several return statements, and which one actually gives the output will depend on flow control. For example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 44,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "def is_even(n):\n",
- " if n % 2 == 0:\n",
- " return True\n",
- " else:\n",
- " return False"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 45,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n",
- "False\n"
- ]
- }
- ],
- "source": [
- "print(is_even(6))\n",
- "print(is_even(37))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This output can be used anywhere in your code. For example, it can be set to a variable:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 46,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "parity = is_even(8)\n",
- "print(parity)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "or used anywhere else:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 47,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "0\n",
- "2\n",
- "4\n",
- "6\n",
- "8\n"
- ]
- }
- ],
- "source": [
- "for x in range(10):\n",
- " if is_even(x):\n",
- " print(x)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Your functions probably should return a value most of the time. Some programmers don't even consider an outputless function to be a function; instead, they will call it a \"procedure\".\n",
- "\n",
- "If you want to return more than one output, just seperate the outputs by commas. The output will be given as a tuple, which you can unpack into seperate variables if you like:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "('Foo', 'Bar')\n",
- "Foo\n",
- "Bar\n"
- ]
- }
- ],
- "source": [
- "def two_outputs():\n",
- " return \"Foo\", \"Bar\"\n",
- "\n",
- "print(two_outputs())\n",
- "out1, out2 = two_outputs()\n",
- "print(out1)\n",
- "print(out2)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Doc-strings\n",
- "\n",
- "As your programs get bigger, and especially if you collaborate with others on your program, making it clear what functions do becomes a bigger and bigger problem. Once you have written a function, you, or your collaborators will not necessarily want to have to read the code to remember how to use it. Mostly, they'll just want to know what inputs to give it, and what output to expect -- the computational details may be no longer relevant. For this purpose, we use a doc-string. A doc-string is a short \"help\" paragraph written just below the function's header, delimited by three quote marks. Let's give is_even() a doc-string. There are no hard rules, so long as it is clear."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "def is_even(n):\n",
- " '''\n",
- " Input: an integer\n",
- " Ouput: a boolean\n",
- " Tells us whether a given integer is even.\n",
- " '''\n",
- " if n % 2 == 0:\n",
- " return True\n",
- " else:\n",
- " return False"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This snippet can even be accessed \"introspectively\" (that is, a program reading its own source code) like so:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Help on function is_even in module __main__:\n",
- "\n",
- "is_even(n)\n",
- " Input: an integer\n",
- " Ouput: a boolean\n",
- " Tells us whether a given integer is even.\n",
- "\n"
- ]
- }
- ],
- "source": [
- "help(is_even)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Basically all functions in Python and its standard library have doc-strings, and writing good, clear doc-strings should become a habit."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 51,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Help on built-in function max in module builtins:\n",
- "\n",
- "max(...)\n",
- " max(iterable, *[, default=obj, key=func]) -> value\n",
- " max(arg1, arg2, *args, *[, key=func]) -> value\n",
- " \n",
- " With a single iterable argument, return its biggest item. The\n",
- " default keyword-only argument specifies an object to return if\n",
- " the provided iterable is empty.\n",
- " With two or more arguments, return the largest argument.\n",
- "\n"
- ]
- }
- ],
- "source": [
- "help(max) # example with the max function"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": true
- },
- "source": [
- "A function can be given additional annotations, included in its docstring, via the following syntax in the header:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "def is_even(n:int) -> bool: # <<< look here\n",
- " '''\n",
- " Tells us whether a given integer is even.\n",
- " '''\n",
- " if n % 2 == 0:\n",
- " return True\n",
- " else:\n",
- " return False"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The int and bool words are ignored by Python when running, but make it clear to the programmer what the input and output of the function will be. It then appears in the function's help file:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Help on function is_even in module __main__:\n",
- "\n",
- "is_even(n:int) -> bool\n",
- " Tells us whether a given integer is even.\n",
- "\n"
- ]
- }
- ],
- "source": [
- "help(is_even)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Worked Example video\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- " \n",
- " "
- ],
- "text/plain": [
- ""
- ]
- },
- "execution_count": 1,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "from IPython.display import YouTubeVideo\n",
- "YouTubeVideo(\"1WCkAA4B2dE\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.1"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 1
-}
diff --git a/PurePy 5. Data Structures/.ipynb_checkpoints/5.0 Data Structures-checkpoint.ipynb b/PurePy 5. Data Structures/.ipynb_checkpoints/5.0 Data Structures-checkpoint.ipynb
deleted file mode 100644
index 91b7589..0000000
--- a/PurePy 5. Data Structures/.ipynb_checkpoints/5.0 Data Structures-checkpoint.ipynb
+++ /dev/null
@@ -1,1062 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Data Structures and Comprehensions\n",
- "\n",
- "Python's data structures are highly flexible and easy to use for a variety of tasks. The basic idea of a data structure to store information in an organized fashion for later use. This tutorial and accompanying video aims to give an overview of the kinds of things Python's data structures can be used for, and how they can be efficiently created out of existing data.\n",
- "\n",
- "## Basic structures\n",
- "\n",
- "### Tuple\n",
- "\n",
- "A tuple is a straightforward way of bundling together a few pieces of related information into an ordered sequence. There is, in general, no expectation that the elements of a tuple be data of the same type. An inventory of products may, for example, be a list of two-element tuples each containing an item (string) and its price (float or integer).\n",
- "\n",
- "There are 3 main ways to create a tuple. We detail two in this section -- the final will be explained later. The first is the so called \"literal\" creation of a tuple. In this case, we use round brackets to simply group the information, separated by commas:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "a_tuple = (\"hello\", 12345)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The elements of a tuple are accessed by index, starting with the first element indexed as 0:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'hello'"
- ]
- },
- "execution_count": 2,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a_tuple[0]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The other way to create a tuple is with the tuple() built-in function, which will attempt to force another structure to take on the structure of a tuple. Any data ordered sequentially, such as a list or string, is an easy candidate. For instance, we can transform a string into a tuple, each containg a single character like so:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "('h', 'e', 'l', 'l', 'o')"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "tuple(\"hello\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Once we have a tuple, it is very easy to assign each element to a variable. The following syntax will \"unpack\" the tuple we created earlier and set each entry to a different variable:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "word, number = a_tuple"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'hello'"
- ]
- },
- "execution_count": 5,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "word"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "12345"
- ]
- },
- "execution_count": 6,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "number"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Another primary use of tuples is in the outputs of functions. A function that returns multiple pieces information is best off returning a tuple containing each item. Then, the function's doc-string (a multi-line comment that appears at the top of the function definition explaining how the function is used) should inform the programmer of what information is returned in the tuple, and in what order. For example, we consider the partition function that can be used on strings. The help() function outputs the function's doc-string:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Help on method_descriptor:\n",
- "\n",
- "partition(...)\n",
- " S.partition(sep) -> (head, sep, tail)\n",
- " \n",
- " Search for the separator sep in S, and return the part before it,\n",
- " the separator itself, and the part after it. If the separator is not\n",
- " found, return S and two empty strings.\n",
- "\n"
- ]
- }
- ],
- "source": [
- "help(str.partition)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "It may look a little cryptic, but the second line says that the partition function takes a separator character, here called \"sep\", as its argument, and the output is a tuple containing three pieces of information. Here is an example. Compare the input and output and compare with the doc-string."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "('Cat', ' | ', 'Dog')"
- ]
- },
- "execution_count": 8,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "\"Cat | Dog\".partition(\" | \")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Using the previous technique of unpacking, it is very easy to assign each piece of this output to different variables:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "before, middle, after = \"Cat | Dog\".partition(\" | \")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'Cat'"
- ]
- },
- "execution_count": 10,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "before"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'Dog'"
- ]
- },
- "execution_count": 11,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "after"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Tuples are an example of an immutable data type. This means that, once created, they cannot be modified. You cannot add or change an entry in a tuple. If you need a tuple to \"change\", then what you must really do is create a new tuple and assign it to the same variable. For instance, let's say I have a pair of numbers (coordinates, say) and wish to add one to each of them. What I must really do is create a new tuple, using the old tuple's information in the process. Example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(6, 4)\n"
- ]
- }
- ],
- "source": [
- "coordinates = (5, 3)\n",
- "# now want new coordinates\n",
- "coordinates = (coordinates[0] + 1, coordinates[1] + 1)\n",
- "print(coordinates)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### List\n",
- "\n",
- "Lists are the workhorse structure of Python. Their use case should be pretty intuitive -- you want to make a list of things. While both are order sequentially, they differ from tuples in several important ways. The first is that there is the expectation that the items in the list are all of the same kind. To consider a real world example, imagine you are looking at your receipt after buying groceries. It is perfectly sensible that our receipt is a list of triples (item, quantity, price). However, we would find it incongruous and possibly incomprehensible if items, quantities, and prices were given as separate items in the list! Second, lists are highly dynamic objects. Their entries can be modified, and they can be extended or reduced on the fly. We say they are \"mutable\". Lists have many functions built into them to facilitate these mutations, and we'll showcase some of the more common ones here. Firstly though, we note that creating a list is very similar to creating a tuple. We have 3 methods for doing it, very similar to the tuple, but using square brackets:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "a_list = [\"One\", \"Two\", \"Three\"]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Also, we have the built-in list() function, which will attempt to turn another data structure into a list. For example, a list can be built from a tuple:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "['Ball', 'Cassidy']"
- ]
- },
- "execution_count": 14,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a_terrible_pair = (\"Ball\", \"Cassidy\") # this is a tuple\n",
- "list( a_terrible_pair ) # this is a list!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "It is very common to loop over the elements of the list, performing an operation on each element. In the loop syntax, we give each element a temporary name while we work on it. Suppose we wish to print each item in lowercase:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "one\n",
- "two\n",
- "three\n"
- ]
- }
- ],
- "source": [
- "for number in a_list: # number is the temporary name given to each item as we work on it\n",
- " print(number.lower())"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "One created, the entries in a list can be modified by simply reassigning that entry using the index:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "['One', 'Zwei', 'Three']\n"
- ]
- }
- ],
- "source": [
- "a_list[1] = \"Zwei\"\n",
- "print(a_list)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "A very common task is to add entries to the end of the list. We can do this using the append() function that lists can perform. It is worth noting, however, that append() is an efficient solution to an inherently costly operation. When you create a list, the program allocates a certain amount of memory to the list; using the append() method may require the program to allocate more memory to the list, which may involve reorganizing other allocated memory. This increases computing time. Therefore, if it is at all possible, it is best to build your list all in one go, rather than construct it by repeated use of append(). Of course, this is not always possible. Using append() is simple:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 17,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "['One', 'Zwei', 'Three', 'Four']\n"
- ]
- }
- ],
- "source": [
- "a_list.append(\"Four\")\n",
- "print(a_list)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "As well as appending, which always adds the new entry to the end of the list, the insert() function takes as its first argument a position in which to add the new entry:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "['Zero', 'One', 'Zwei', 'Three', 'Four']\n"
- ]
- }
- ],
- "source": [
- "a_list.insert(0, \"Zero\")\n",
- "print(a_list)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The syntax for deleting a list element is a bit different. We write it like this:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 19,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "['One', 'Zwei', 'Three', 'Four']\n"
- ]
- }
- ],
- "source": [
- "del a_list[0]\n",
- "print(a_list)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The final list operation I'd like to show here is pop(). Pop takes an index as its argument, and outputs the element that index refers to. However, it then deletes the element from the list. In this way, we can think of a list as a container, and when we \"pop\" an item from the list, we take it out of the container to do something with it. From our list, we have:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 20,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "THREE\n",
- "['One', 'Zwei', 'Four']\n"
- ]
- }
- ],
- "source": [
- "an_item = a_list.pop(2)\n",
- "print(an_item.upper())\n",
- "print(a_list)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Using pop() with no argument performs this operation on the last element of the list. This leads to a certain kind of algorithm \"first in, last out\". Conceive of the list as a pile of cards. You can add a card to the top of the stack, or remove the top card. Therefore, the card added first, will be the last card to be retreived.\n",
- "\n",
- "Let's do an example of this kind of algorithm. Mathematical expressions often use brackets to inform us of the correct order to perform the operations. Suppose we want our program to take a mathematical expression containing brackets, and check that every opening bracket has a corresponding closing bracket, and vice versa. The following code will do this very task:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 21,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "def check_brackets(expression):\n",
- " bracket_list = []\n",
- " for character in expression:\n",
- " if character == \"(\":\n",
- " bracket_list.append(character) #add opening brackets to the end of the list\n",
- " if character == \")\":\n",
- " if len(bracket_list) == 0: \n",
- " # the list is empty, so there must be no corresponding opening bracket!\n",
- " return False\n",
- " else:\n",
- " # if there's matching opening bracket, remove it from the list!\n",
- " bracket_list.pop()\n",
- " \n",
- " # returns True only if bracket_list is empty at the end (all brackets were matched)\n",
- " return len(bracket_list) == 0 \n",
- " \n",
- "\n",
- "print(check_brackets(\"5 * (6 + (4 - (5 * 6)))\"))\n",
- " "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 22,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(check_brackets(\"5 * 5 + ((3+4)\"))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "A 2d grid of values can be represented as a list of lists, and values can be looked up by using two indices. A chessboard for a chess game could have the following representation:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 23,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "bP\n"
- ]
- }
- ],
- "source": [
- "board = [\n",
- " [\"bR\", \"bN\", \"bB\", \"bQ\", \"bK\", \"bB\", \"bN\", \"bR\"],\n",
- " [\"bP\", \"bP\", \"bP\", \"bP\", \"bP\", \"bP\", \"bP\", \"bP\"],\n",
- " [ \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" ],\n",
- " [ \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" ],\n",
- " [ \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" ],\n",
- " [ \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" ],\n",
- " [\"wP\", \"wP\", \"wP\", \"wP\", \"wP\", \"wP\", \"wP\", \"wP\"],\n",
- " [\"wR\", \"wN\", \"wB\", \"wQ\", \"wK\", \"wB\", \"wN\", \"wR\"]]\n",
- "\n",
- "# look up what piece is in a square\n",
- "print(board[1][3])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Dictionaries\n",
- "\n",
- "Dictionaries are one of the nicest structures in Python. With our previous structures, we could only retreive elements by index -- that is, by the order in which they appear. However, it is very common that the order is not important to us, and we wish to use a word or other identifier to retreive the item from the structure. This is where dictionaries come in. A dictionary is a \"key-value pair\" -- the key is the word (or other identifier) we use to obtain the value. To create a dictionary, we use curly braces. For example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 24,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Berlin\n"
- ]
- }
- ],
- "source": [
- "capital_cities = {\"UK\": \"London\",\n",
- " \"India\": \"New Delhi\",\n",
- " \"Germany\": \"Berlin\"}\n",
- "print(capital_cities[\"Germany\"])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 25,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "London\n"
- ]
- }
- ],
- "source": [
- "beekeeper = {\"Name\": \"Sam\", \"Country\": \"UK\"}\n",
- "\n",
- "print(capital_cities[beekeeper[\"Country\"]]) # briefly ponder what this line does"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Keys must be immutable -- objects that cannot be changed. Strings and numbers are good examples of immutable data types. Values can be anything you like. Strings, numbers, lists, even functions! Adding an item to a dictionary is as simple as this:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 26,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "capital_cities[\"Russia\"] = \"Moscow\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Dictionaries can be looped over just like lists, but it is usually less clear in what order the items will be looped over, so make sure what you are doing doesn't depend too heavily on the order the operations are performed:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 27,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "UK\n",
- "India\n",
- "Germany\n",
- "Russia\n"
- ]
- }
- ],
- "source": [
- "for country in capital_cities:\n",
- " print(country)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Deleting an item from a dictionary is akin to doing the same for a list:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 28,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "del capital_cities[\"UK\"]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 29,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "{'India': 'New Delhi', 'Germany': 'Berlin', 'Russia': 'Moscow'}\n"
- ]
- }
- ],
- "source": [
- "print(capital_cities)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "So, when do we use a dictionary? A key feature of dictionaries is that they allow us to assign words to other objects. This sounds remeniscent of variables, with which we are already very familiar. The difference is that variables are something created by the programmer to appear in the source code. The keys of a dictionary can be created by the program itself as it is running. Suppose your program is running and creating lots of new data, and you want to assign names to the different bits of data you are creating as the program is running. The program cannot create a new variable. But it can put the data into a dictionary and give it a key!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Exercises with data structures\n",
- "\n",
- "1. Create a list of 4 tuples, each being a pair containing a \n",
- "2. Use the dict() function on the list from exercise 1. Note how this is similar to the tuple() and list() functions. Give the dictionary a name like temp\n",
- "3. Create a for-loop that prints the items in the dictionary created in problem 2. Notice how this only prints the keys of the dictionary. Now loop over temp.values() instead of temp, and see what happens. What happens if you loop over temp.items()? What data structures does .items() return?\n",
- "4. (challenge) Modify the check_brackets() code above so that it checks the validity of expressions containing a combination of round, square and curly brackets. Hint: Create a dictionary that associates each kind of opening bracket to its appropriate closing bracket (e.g [ to ]).\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Comprehensions\n",
- "\n",
- "Now we get to something interesting and very useful. So far, we have been constructing tuples, lists and dictionaries by specifying the items individually. This is all very well, but for large structures, it could take forever! A comprehension is a line of code that specifies how to create a structure by describing the objects in it, rather than stating each one explicitly. We will focus here on list comprehensions, but the syntax is very similar for the other structures.\n",
- "\n",
- "Suppose we wish to create a list containing the numbers 0 to 99. A naive way to achieve this task might be:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 30,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "numbers = []\n",
- "for x in range(100):\n",
- " numbers.append(x)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "As mentioned above, this repeated use of append() is slow -- it would be faster to create the list containing all the numbers at once, rather than constantly modifying the size of the list. This is where list comprehensions come in. The correct syntax, which we will break down in just a moment is:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 31,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "numbers = [x for x in range(100)]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Both of these snippets achieve the same task, but one is shorter, clearer, and faster. Let's take a quick look at the syntax. Note first that we still use square brackets to create the list (if we wanted to use a tuple comprehension, we'd use round brackets). Now, what is this \"x for x\" business? Look first at the latter part of the syntax. It should look exactly like the header of a for-loop for x in range(100). The first x is any expression that should be evaluated for each x before putting the result into the list. In this case, an example really does speak a thousand words:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 32,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961, 1024, 1089, 1156, 1225, 1296, 1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936, 2025, 2116, 2209, 2304, 2401, 2500, 2601, 2704, 2809, 2916, 3025, 3136, 3249, 3364, 3481, 3600, 3721, 3844, 3969, 4096, 4225, 4356, 4489, 4624, 4761, 4900, 5041, 5184, 5329, 5476, 5625, 5776, 5929, 6084, 6241, 6400, 6561, 6724, 6889, 7056, 7225, 7396, 7569, 7744, 7921, 8100, 8281, 8464, 8649, 8836, 9025, 9216, 9409, 9604, 9801]\n"
- ]
- }
- ],
- "source": [
- "numbers = [x**2 for x in range(100)]\n",
- "print(numbers)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Imagine how long it would have taken to construct this list manually. We have squared each number before adding it to the list. The expression to evaluate can be pretty much anything! For example, we create a list here of tuples containing each number, and whether or not it is prime:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 33,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "def is_prime(n):\n",
- " '''basic function to determine if a number is prime'''\n",
- " if n < 2:\n",
- " return False\n",
- " for i in range(2, int(n**(0.5)+1)):\n",
- " if n % i == 0:\n",
- " return False\n",
- " return True\n",
- "\n",
- "prime_list = [(p, is_prime(p)) for p in range(20)] # here's the list comprehension!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 34,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(0, False)\n",
- "(1, False)\n",
- "(2, True)\n",
- "(3, True)\n",
- "(4, False)\n",
- "(5, True)\n",
- "(6, False)\n",
- "(7, True)\n",
- "(8, False)\n",
- "(9, False)\n",
- "(10, False)\n",
- "(11, True)\n",
- "(12, False)\n",
- "(13, True)\n",
- "(14, False)\n",
- "(15, False)\n",
- "(16, False)\n",
- "(17, True)\n",
- "(18, False)\n",
- "(19, True)\n"
- ]
- }
- ],
- "source": [
- "# Now let's view the list\n",
- "for pair in prime_list:\n",
- " print(pair)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "A list comprehension can also contain if clauses. We could create a list of the prime numbers less than 1000 with the following code:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 35,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]\n"
- ]
- }
- ],
- "source": [
- "prime_list = [p for p in range(1000) if is_prime(p)]\n",
- "print(prime_list)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This just about covers the power of list comprehensions. Of course, these have only been toy examples, creating lists of numbers with various properties. List comprehensions can be used to construct lists of pretty much anything. In our demonstration video today, we use list comprehensions to solve a problem that involves extracting data from a file and storing that data in a list.\n",
- "\n",
- "It is potentially useful when you are just beginning Python, to work always with the Data Structures page from the manual open https://docs.python.org/3/tutorial/datastructures.html. A large amount of what we do when programming is organizing and retrieving data in structures, so having a reference to all the basic tasks Python can do with its structures is extremely useful!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercises with comprehensions\n",
- "\n",
- "1. Create a list containg the first 10 numbers in the 3 times table, using a comprehension.\n",
- "2. Now create a list of 10 lists, with the $k$th list being the first 10 numbers of the $k$ times table, using a list comprehension within a list comprehension (\"nested\").\n",
- "3. Head over to https://docs.python.org/3/, the website that contains Python's instruction manual. It's enormous, but knowing your way around it is extremely important for your development as a Python programmer. Try to find the section that explains how to make a dictionary comprehension, and try it out yourself."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": true
- },
- "source": [
- "## Example video\n",
- "\n",
- "In the following example video, we make use of tuples, dictionaries, and list comprehensions to solve a problem."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 36,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "image/jpeg": "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\nREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERA\nREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQERE\nBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERARE\nQEREBERAREQEREBERAREQEREBERAREQEREH/2Q==\n",
- "text/html": [
- "\n",
- " \n",
- " "
- ],
- "text/plain": [
- ""
- ]
- },
- "execution_count": 36,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "from IPython.display import YouTubeVideo\n",
- "YouTubeVideo(\"TXiTmmlKmKY\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Footnote to the video\n",
- "\n",
- "In the video, we implement a counting dictionary. Python's standard library includes an easier and more powerful way to produce a counting dictionary:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 37,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Counter({'B': 2, 'A': 1, 'C': 1})\n"
- ]
- }
- ],
- "source": [
- "from collections import Counter\n",
- "\n",
- "a_list = ['A', 'B', 'B', 'C']\n",
- "count = Counter(a_list)\n",
- "print(count)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 38,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Most common name is [('John', 60)]\n"
- ]
- }
- ],
- "source": [
- "# Hence the same problem from the video can be solved like this:\n",
- "\n",
- "with open(\"Directory.txt\") as f:\n",
- " namecount = Counter([line.partition(\"\\t\")[0] for line in f])\n",
- "\n",
- "print(\"Most common name is\", namecount.most_common(1))\n",
- "# dictionaries provided by Counter come with a function called most_common"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This dictionary comes equipped with some additional features (exactly how this works will be explained in the Object Oriented Programming articles), but the counting algorithm is virtually the same as ours, and seeing algorithms like this is good for the soul of any programmer. "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Practice Makes Perfect\n",
- "\n",
- "Now equipped with a basic knowledge of functions, data structures, mathematical operations and flow control, you are pretty much ready to start using Python to try to solve simple problems. It's now up to you to practice. Not sure about something? Python's documentation and the excellent programming question and answer website stackoverflow.com will almost certainly have the solution.\n",
- "\n",
- "Not sure where to begin practising? Here's some recommendations:\n",
- "\n",
- "1) Come up with a simple project of your own to solve.\n",
- "\n",
- "2) checkio.org is a fantastic website with an enormous selection of Python programming challenges. The objective of each challenge is to write a function in the browser window that completes a certain task, and then the website itself will test if your function really does meet the required criteria. Once you've solved it you can read other people's solutions to get tips on how to do it better.\n",
- "\n",
- "3) If you enjoy a little mathematics, projecteuler.net is a website that provides mathematical problems that are best solved with the aid of a computer and a programming language such as Python. There are hundreds, and they range from very easy (beginning with a variation on Fizzbuzz!) to obscenely difficult."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.1"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 1
-}
diff --git a/PurePy 5. Data Structures/.ipynb_checkpoints/datastructures-checkpoint.ipynb b/PurePy 5. Data Structures/.ipynb_checkpoints/datastructures-checkpoint.ipynb
deleted file mode 100644
index fc64c44..0000000
--- a/PurePy 5. Data Structures/.ipynb_checkpoints/datastructures-checkpoint.ipynb
+++ /dev/null
@@ -1,1074 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Data Structures and Comprehensions\n",
- "\n",
- "Python's data structures are highly flexible and easy to use for a variety of tasks. The basic idea of a data structure to store information in an organized fashion for later use. This tutorial and accompanying video aims to give an overview of the kinds of things Python's data structures can be used for, and how they can be efficiently created out of existing data.\n",
- "\n",
- "## Basic structures\n",
- "\n",
- "### Tuple\n",
- "\n",
- "A tuple is a straightforward way of bundling together a few pieces of related information into an ordered sequence. There is, in general, no expectation that the elements of a tuple be data of the same type. An inventory of products may, for example, be a list of two-element tuples each containing an item (string) and its price (float or integer).\n",
- "\n",
- "There are 3 main ways to create a tuple. We detail two in this section -- the final will be explained later. The first is the so called \"literal\" creation of a tuple. In this case, we use round brackets to simply group the information, separated by commas:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "a_tuple = (\"hello\", 12345)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The elements of a tuple are accessed by index, starting with the first element indexed as 0:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'hello'"
- ]
- },
- "execution_count": 2,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a_tuple[0]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The other way to create a tuple is with the tuple() built-in function, which will attempt to force another structure to take on the structure of a tuple. Any data ordered sequentially, such as a list or string, is an easy candidate. For instance, we can transform a string into a tuple, each containg a single character like so:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "('h', 'e', 'l', 'l', 'o')"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "tuple(\"hello\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Once we have a tuple, it is very easy to assign each element to a variable. The following syntax will \"unpack\" the tuple we created earlier and set each entry to a different variable:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "word, number = a_tuple"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'hello'"
- ]
- },
- "execution_count": 5,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "word"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "12345"
- ]
- },
- "execution_count": 6,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "number"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Another primary use of tuples is in the outputs of functions. A function that returns multiple pieces information is best off returning a tuple containing each item. Then, the function's doc-string (a multi-line comment that appears at the top of the function definition explaining how the function is used) should inform the programmer of what information is returned in the tuple, and in what order. For example, we consider the partition function that can be used on strings. The help() function outputs the function's doc-string:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Help on method_descriptor:\n",
- "\n",
- "partition(...)\n",
- " S.partition(sep) -> (head, sep, tail)\n",
- " \n",
- " Search for the separator sep in S, and return the part before it,\n",
- " the separator itself, and the part after it. If the separator is not\n",
- " found, return S and two empty strings.\n",
- "\n"
- ]
- }
- ],
- "source": [
- "help(str.partition)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "It may look a little cryptic, but the second line says that the partition function takes a separator character, here called \"sep\", as its argument, and the output is a tuple containing three pieces of information. Here is an example. Compare the input and output and compare with the doc-string."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "('Cat', ' | ', 'Dog')"
- ]
- },
- "execution_count": 8,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "\"Cat | Dog\".partition(\" | \")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Using the previous technique of unpacking, it is very easy to assign each piece of this output to different variables:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "before, middle, after = \"Cat | Dog\".partition(\" | \")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'Cat'"
- ]
- },
- "execution_count": 10,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "before"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'Dog'"
- ]
- },
- "execution_count": 11,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "after"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Tuples are an example of an immutable data type. This means that, once created, they cannot be modified. You cannot add or change an entry in a tuple. If you need a tuple to \"change\", then what you must really do is create a new tuple and assign it to the same variable. For instance, let's say I have a pair of numbers (coordinates, say) and wish to add one to each of them. What I must really do is create a new tuple, using the old tuple's information in the process. Example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(6, 4)\n"
- ]
- }
- ],
- "source": [
- "coordinates = (5, 3)\n",
- "# now want new coordinates\n",
- "coordinates = (coordinates[0] + 1, coordinates[1] + 1)\n",
- "print(coordinates)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### List\n",
- "\n",
- "Lists are the workhorse structure of Python. Their use case should be pretty intuitive -- you want to make a list of things. While both are order sequentially, they differ from tuples in several important ways. The first is that there is the expectation that the items in the list are all of the same kind. To consider a real world example, imagine you are looking at your receipt after buying groceries. It is perfectly sensible that our receipt is a list of triples (item, quantity, price). However, we would find it incongruous and possibly incomprehensible if items, quantities, and prices were given as separate items in the list! Second, lists are highly dynamic objects. Their entries can be modified, and they can be extended or reduced on the fly. We say they are \"mutable\". Lists have many functions built into them to facilitate these mutations, and we'll showcase some of the more common ones here. Firstly though, we note that creating a list is very similar to creating a tuple. We have 3 methods for doing it, very similar to the tuple, but using square brackets:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 32,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "a_list = [\"One\", \"Two\", \"Three\"]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Also, we have the built-in list() function, which will attempt to turn another data structure into a list. For example, a list can be built from a tuple:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 33,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "['Ball', 'Cassidy']"
- ]
- },
- "execution_count": 33,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a_terrible_pair = (\"Ball\", \"Cassidy\") # this is a tuple\n",
- "list( a_terrible_pair ) # this is a list!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "It is very common to loop over the elements of the list, performing an operation on each element. In the loop syntax, we give each element a temporary name while we work on it. Suppose we wish to print each item in lowercase:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 34,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "one\n",
- "two\n",
- "three\n"
- ]
- }
- ],
- "source": [
- "for number in a_list: # number is the temporary name given to each item as we work on it\n",
- " print(number.lower())"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "One created, the entries in a list can be modified by simply reassigning that entry using the index:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 35,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "['One', 'Zwei', 'Three']\n"
- ]
- }
- ],
- "source": [
- "a_list[1] = \"Zwei\"\n",
- "print(a_list)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "A very common task is to add entries to the end of the list. We can do this using the append() function that lists can perform. It is worth noting, however, that append() is an efficient solution to an inherently costly operation. When you create a list, the program allocates a certain amount of memory to the list; using the append() method may require the program to allocate more memory to the list, which may involve reorganizing other allocated memory. This increases computing time. Therefore, if it is at all possible, it is best to build your list all in one go, rather than construct it by repeated use of append(). Of course, this is not always possible. Using append() is simple:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "['One', 'Zwei', 'Three', 'Four']\n"
- ]
- }
- ],
- "source": [
- "a_list.append(\"Four\")\n",
- "print(a_list)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "As well as appending, which always adds the new entry to the end of the list, the insert() function takes as its first argument a position in which to add the new entry:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 17,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "['Zero', 'One', 'Zwei', 'Three', 'Four']\n"
- ]
- }
- ],
- "source": [
- "a_list.insert(0, \"Zero\")\n",
- "print(a_list)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The syntax for deleting a list element is a bit different. We write it like this:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "['One', 'Zwei', 'Three', 'Four']\n"
- ]
- }
- ],
- "source": [
- "del a_list[0]\n",
- "print(a_list)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The final list operation I'd like to show here is pop(). Pop takes an index as its argument, and outputs the element that index refers to. However, it then deletes the element from the list. In this way, we can think of a list as a container, and when we \"pop\" an item from the list, we take it out of the container to do something with it. From our list, we have:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 19,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "THREE\n",
- "['One', 'Zwei', 'Four']\n"
- ]
- }
- ],
- "source": [
- "an_item = a_list.pop(2)\n",
- "print(an_item.upper())\n",
- "print(a_list)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Using pop() with no argument performs this operation on the last element of the list. This leads to a certain kind of algorithm \"first in, last out\". Conceive of the list as a pile of cards. You can add a card to the top of the stack, or remove the top card. Therefore, the card added first, will be the last card to be retreived.\n",
- "\n",
- "Let's do an example of this kind of algorithm. Mathematical expressions often use brackets to inform us of the correct order to perform the operations. Suppose we want our program to take a mathematical expression containing brackets, and check that every opening bracket has a corresponding closing bracket, and vice versa. The following code will do this very task:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 49,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "def check_brackets(expression):\n",
- " bracket_list = []\n",
- " for character in expression:\n",
- " if character == \"(\":\n",
- " bracket_list.append(character) #add opening brackets to the end of the list\n",
- " if character == \")\":\n",
- " if len(bracket_list) == 0: \n",
- " # the list is empty, so there must be no corresponding opening bracket!\n",
- " return False\n",
- " else:\n",
- " # if there's matching opening bracket, remove it from the list!\n",
- " bracket_list.pop()\n",
- " \n",
- " # returns True only if bracket_list is empty at the end (all brackets were matched)\n",
- " return len(bracket_list) == 0 \n",
- " \n",
- "\n",
- "print(check_brackets(\"5 * (6 + (4 - (5 * 6)))\"))\n",
- " "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 30,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(check_brackets(\"5 * 5 + ((3+4)\"))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "A 2d grid of values can be represented as a list of lists, and values can be looked up by using two indices. A chessboard for a chess game could have the following representation:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 38,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'bP'"
- ]
- },
- "execution_count": 38,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "board = [\n",
- " [\"bR\", \"bN\", \"bB\", \"bQ\", \"bK\", \"bB\", \"bN\", \"bR\"],\n",
- " [\"bP\", \"bP\", \"bP\", \"bP\", \"bP\", \"bP\", \"bP\", \"bP\"],\n",
- " [ \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" ],\n",
- " [ \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" ],\n",
- " [ \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" ],\n",
- " [ \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" , \"\" ],\n",
- " [\"wP\", \"wP\", \"wP\", \"wP\", \"wP\", \"wP\", \"wP\", \"wP\"],\n",
- " [\"wR\", \"wN\", \"wB\", \"wQ\", \"wK\", \"wB\", \"wN\", \"wR\"]]\n",
- "\n",
- "# look up what piece is in a square\n",
- "print(board[1][3])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Dictionaries\n",
- "\n",
- "Dictionaries are one of the nicest structures in Python. With our previous structures, we could only retreive elements by index -- that is, by the order in which they appear. However, it is very common that the order is not important to us, and we wish to use a word or other identifier to retreive the item from the structure. This is where dictionaries come in. A dictionary is a \"key-value pair\" -- the key is the word (or other identifier) we use to obtain the value. To create a dictionary, we use curly braces. For example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 41,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'Berlin'"
- ]
- },
- "execution_count": 41,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "capital_cities = {\"UK\": \"London\",\n",
- " \"India\": \"New Delhi\",\n",
- " \"Germany\": \"Berlin\"}\n",
- "print(capital_cities[\"Germany\"])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 43,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'London'"
- ]
- },
- "execution_count": 43,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "beekeeper = {\"Name\": \"Sam\", \"Country\": \"UK\"}\n",
- "\n",
- "print(capital_cities[beekeeper[\"Country\"]]) # briefly ponder what this line does"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Keys must be immutable -- objects that cannot be changed. Strings and numbers are good examples of immutable data types. Values can be anything you like. Strings, numbers, lists, even functions! Adding an item to a dictionary is as simple as this:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 44,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "capital_cities[\"Russia\"] = \"Moscow\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Dictionaries can be looped over just like lists, but it is usually less clear in what order the items will be looped over, so make sure what you are doing doesn't depend too heavily on the order the operations are performed:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 46,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "India\n",
- "Russia\n",
- "UK\n",
- "Germany\n"
- ]
- }
- ],
- "source": [
- "for country in capital_cities:\n",
- " print(country)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Deleting an item from a dictionary is akin to doing the same for a list:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 47,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "del capital_cities[\"UK\"]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 48,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "{'Germany': 'Berlin', 'India': 'New Delhi', 'Russia': 'Moscow'}"
- ]
- },
- "execution_count": 48,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "print(capital_cities)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "So, when do we use a dictionary? A key feature of dictionaries is that they allow us to assign words to other objects. This sounds remeniscent of variables, with which we are already very familiar. The difference is that variables are something created by the programmer to appear in the source code. The keys of a dictionary can be created by the program itself as it is running. Suppose your program is running and creating lots of new data, and you want to assign names to the different bits of data you are creating as the program is running. The program cannot create a new variable. But it can put the data into a dictionary and give it a key!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Exercises with data structures\n",
- "\n",
- "1. Create a list of 4 tuples, each being a pair containing a \n",
- "2. Use the dict() function on the list from exercise 1. Note how this is similar to the tuple() and list() functions. Give the dictionary a name like temp\n",
- "3. Create a for-loop that prints the items in the dictionary created in problem 2. Notice how this only prints the keys of the dictionary. Now loop over temp.values() instead of temp, and see what happens. What happens if you loop over temp.items()? What data structures does .items() return?\n",
- "4. (challenge) Modify the check_brackets() code above so that it checks the validity of expressions containing a combination of round, square and curly brackets. Hint: Create a dictionary that associates each kind of opening bracket to its appropriate closing bracket (e.g [ to ]).\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Comprehensions\n",
- "\n",
- "Now we get to something interesting and very useful. So far, we have been constructing tuples, lists and dictionaries by specifying the items individually. This is all very well, but for large structures, it could take forever! A comprehension is a line of code that specifies how to create a structure by describing the objects in it, rather than stating each one explicitly. We will focus here on list comprehensions, but the syntax is very similar for the other structures.\n",
- "\n",
- "Suppose we wish to create a list containing the numbers 0 to 99. A naive way to achieve this task might be:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 50,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "numbers = []\n",
- "for x in range(100):\n",
- " numbers.append(x)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "As mentioned above, this repeated use of append() is slow -- it would be faster to create the list containing all the numbers at once, rather than constantly modifying the size of the list. This is where list comprehensions come in. The correct syntax, which we will break down in just a moment is:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 51,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "numbers = [x for x in range(100)]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Both of these snippets achieve the same task, but one is shorter, clearer, and faster. Let's take a quick look at the syntax. Note first that we still use square brackets to create the list (if we wanted to use a tuple comprehension, we'd use round brackets). Now, what is this \"x for x\" business? Look first at the latter part of the syntax. It should look exactly like the header of a for-loop for x in range(100). The first x is any expression that should be evaluated for each x before putting the result into the list. In this case, an example really does speak a thousand words:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 53,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576, 625, 676, 729, 784, 841, 900, 961, 1024, 1089, 1156, 1225, 1296, 1369, 1444, 1521, 1600, 1681, 1764, 1849, 1936, 2025, 2116, 2209, 2304, 2401, 2500, 2601, 2704, 2809, 2916, 3025, 3136, 3249, 3364, 3481, 3600, 3721, 3844, 3969, 4096, 4225, 4356, 4489, 4624, 4761, 4900, 5041, 5184, 5329, 5476, 5625, 5776, 5929, 6084, 6241, 6400, 6561, 6724, 6889, 7056, 7225, 7396, 7569, 7744, 7921, 8100, 8281, 8464, 8649, 8836, 9025, 9216, 9409, 9604, 9801]\n"
- ]
- }
- ],
- "source": [
- "numbers = [x**2 for x in range(100)]\n",
- "print(numbers)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Imagine how long it would have taken to construct this list manually. We have squared each number before adding it to the list. The expression to evaluate can be pretty much anything! For example, we create a list here of tuples containing each number, and whether or not it is prime:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 90,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "def is_prime(n):\n",
- " '''basic function to determine if a number is prime'''\n",
- " if n < 2:\n",
- " return False\n",
- " for i in range(2, int(n**(0.5)+1)):\n",
- " if n % i == 0:\n",
- " return False\n",
- " return True\n",
- "\n",
- "prime_list = [(p, is_prime(p)) for p in range(20)] # here's the list comprehension!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 91,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(0, False)\n",
- "(1, False)\n",
- "(2, True)\n",
- "(3, True)\n",
- "(4, False)\n",
- "(5, True)\n",
- "(6, False)\n",
- "(7, True)\n",
- "(8, False)\n",
- "(9, False)\n",
- "(10, False)\n",
- "(11, True)\n",
- "(12, False)\n",
- "(13, True)\n",
- "(14, False)\n",
- "(15, False)\n",
- "(16, False)\n",
- "(17, True)\n",
- "(18, False)\n",
- "(19, True)\n"
- ]
- }
- ],
- "source": [
- "# Now let's view the list\n",
- "for pair in prime_list:\n",
- " print(pair)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "A list comprehension can also contain if clauses. We could create a list of the prime numbers less than 1000 with the following code:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 92,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]\n"
- ]
- }
- ],
- "source": [
- "prime_list = [p for p in range(1000) if is_prime(p)]\n",
- "print(prime_list)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This just about covers the power of list comprehensions. Of course, these have only been toy examples, creating lists of numbers with various properties. List comprehensions can be used to construct lists of pretty much anything. In our demonstration video today, we use list comprehensions to solve a problem that involves extracting data from a file and storing that data in a list.\n",
- "\n",
- "It is potentially useful when you are just beginning Python, to work always with the Data Structures page from the manual open https://docs.python.org/3/tutorial/datastructures.html. A large amount of what we do when programming is organizing and retrieving data in structures, so having a reference to all the basic tasks Python can do with its structures is extremely useful!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercises with comprehensions\n",
- "\n",
- "1. Create a list containg the first 10 numbers in the 3 times table, using a comprehension.\n",
- "2. Now create a list of 10 lists, with the $k$th list being the first 10 numbers of the $k$ times table, using a list comprehension within a list comprehension (\"nested\").\n",
- "3. Head over to https://docs.python.org/3/, the website that contains Python's instruction manual. It's enormous, but knowing your way around it is extremely important for your development as a Python programmer. Try to find the section that explains how to make a dictionary comprehension, and try it out yourself."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": true
- },
- "source": [
- "## Example video\n",
- "\n",
- "In the following example video, we make use of tuples, dictionaries, and list comprehensions to solve a problem."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "image/jpeg": "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\nREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERA\nREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQERE\nBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERARE\nQEREBERAREQEREBERAREQEREBERAREQEREH/2Q==\n",
- "text/html": [
- "\n",
- " \n",
- " "
- ],
- "text/plain": [
- ""
- ]
- },
- "execution_count": 1,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "from IPython.display import YouTubeVideo\n",
- "YouTubeVideo(\"TXiTmmlKmKY\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Footnote to the video\n",
- "\n",
- "In the video, we implement a counting dictionary. Python's standard library includes an easier and more powerful way to produce a counting dictionary:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Counter({'B': 2, 'A': 1, 'C': 1})\n"
- ]
- }
- ],
- "source": [
- "from collections import Counter\n",
- "\n",
- "a_list = ['A', 'B', 'B', 'C']\n",
- "count = Counter(a_list)\n",
- "print(count)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Most common name is [('John', 60)]\n"
- ]
- }
- ],
- "source": [
- "# Hence the same problem from the video can be solved like this:\n",
- "\n",
- "with open(\"Directory.txt\") as f:\n",
- " namecount = Counter([line.partition(\"\\t\")[0] for line in f])\n",
- "\n",
- "print(\"Most common name is\", namecount.most_common(1))\n",
- "# dictionaries provided by Counter come with a function called most_common"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This dictionary comes equipped with some additional features (exactly how this works will be explained in the Object Oriented Programming articles), but the counting algorithm is virtually the same as ours, and seeing algorithms like this is good for the soul of any programmer. "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Practice Makes Perfect\n",
- "\n",
- "Now equipped with a basic knowledge of functions, data structures, mathematical operations and flow control, you are pretty much ready to start using Python to try to solve simple problems. It's now up to you to practice. Not sure about something? Python's documentation and the excellent programming question and answer website stackoverflow.com will almost certainly have the solution.\n",
- "\n",
- "Not sure where to begin practising? Here's some recommendations:\n",
- "\n",
- "1) Come up with a simple project of your own to solve.\n",
- "\n",
- "2) checkio.org is a fantastic website with an enormous selection of Python programming challenges. The objective of each challenge is to write a function in the browser window that completes a certain task, and then the website itself will test if your function really does meet the required criteria. Once you've solved it you can read other people's solutions to get tips on how to do it better.\n",
- "\n",
- "3) If you enjoy a little mathematics, projecteuler.net is a website that provides mathematical problems that are best solved with the aid of a computer and a programming language such as Python. There are hundreds, and they range from very easy (beginning with a variation on Fizzbuzz!) to obscenely difficult."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.5.2"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 1
-}
diff --git a/PurePy 5.5 Command-line interlude/.ipynb_checkpoints/0.2 The command line-checkpoint.ipynb b/PurePy 5.5 Command-line interlude/.ipynb_checkpoints/0.2 The command line-checkpoint.ipynb
deleted file mode 100644
index f8fb76c..0000000
--- a/PurePy 5.5 Command-line interlude/.ipynb_checkpoints/0.2 The command line-checkpoint.ipynb
+++ /dev/null
@@ -1,485 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "\n",
- "# A very short introduction introduction to command-line computing\n",
- "\n",
- "This article is not about Python. But it is worth the time of any new Python programmer, or anyone who uses computers a lot. We have to have a discussion about the command-line. Most of us in the modern era have grown up using a graphical user interface (GUI) to interact with our computers. This is where we use a mouse or touch screen to press on-screen buttons, drag-and-drop files, highlight text, move a scroll bar, or bring up a menu. But there is another method, in which we interact with the computer by typing in text commands, and getting text output. For many, this is an ancient relic seen only in films such as The Matrix, War Games, or Hackers, but in the world of computers and computer programming, it remains an invaluable tool.\n",
- "\n",
- "Now the command-line isn't pretty, and takes a little practice to learn. Most commercial software is no longer written for the command-line for this reason. But as Python beginners, we're generally going to be writing programs that:\n",
- "1. Takes some input,\n",
- "2. Performs some task or computation,\n",
- "3. Gives some output,\n",
- "\n",
- "rather than writing commercial software. For this purpose, a text-based, command-line is quicker, easier, and just as effective.\n",
- "\n",
- "Reasons to learn basic command-line skills:\n",
- "- Command-line software is easier to write than graphical software.\n",
- "- Many tasks easier and faster with the command-line.\n",
- "- Access to vast repositories of free command-line software.\n",
- "- More freedom to tinker with the workings of your computer.\n",
- "- Feel like a hacker.\n",
- "\n",
- "That said, there are still many tasks which lend themselves better to the graphical interface. I don't know many people, for instance, who manage their emails from the command-line (though such masochists do exist). It's just about choosing the correct tool for the job."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Before we begin, three basic terms. A command-line is any computer interface in which you type text commands rather than click buttons to make things happen. A terminal or terminal emulator is a piece of software on your computer that displays the text for a command-line interface. Finally, a shell is the software \"behind the scenes\", that interprets your commands, performs the tasks you ask of it, and then displays the result in your terminal. These words are sometimes used somewhat interchangeably. Something like \"type this command into the command-line\", \"type this command into the terminal\", \"type this command into the shell\" all mean basically the same thing."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Accessing a command-line\n",
- "\n",
- "The precise software you use will depend on your operating system. If it is at all possible, you should try to use the Bash shell. This has become the standard shell across Mac OSX and Linux operating systems. It is now also available as an experimental feature of Windows 10: see [here](https://www.howtogeek.com/249966/how-to-install-and-use-the-linux-bash-shell-on-windows-10/) for installation instructions. If you are on Windows, but either you do not have Windows 10 or you do not want to install Bash for some reason, then you can use a software that comes with Windows call Powershell. The most basic commands of Powershell and Bash are roughly the same, and most of the things we learn in this tutorial are applicable to Bash and Powershell.\n",
- "\n",
- "* On Windows, either follow the Bash instructions above, or go to the Start Menu, type Powershell, and open the software it suggests. Note that in Powershell you might have to use backslashes instead of slashes for file paths.\n",
- "* On OSX, press cmd+space. This will open the spotlight, which can access any file or program on your computer. Type Terminal, and you will shown the correct software on the menu. Consider adding the terminal to your dock, as it is very useful to have quick access.\n",
- "* On Linux systems, go to whatever interface you usually use to open software. If you're on Ubuntu or GNOME or something, try the gnome-terminal, usually accessible just be typing \"Terminal\". If you are on another operating system, you might not have gnome-terminal, but you will definitely have xterm or some equivalent, so try searching for xterm.\n",
- "\n",
- "Now after allowing everything to load, you should see some kind of command-prompt. On Powershell, I think it will end with a > symbol. In Bash, it will probably be a $ sign. This means the command-line is ready to take commands."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Will I break my computer?\n",
- "\n",
- "Probably not. There are several checks to make sure you do not do anything dangerous unwittingly. The command for deleting files requires special permissions to delete entire folders, for example. In Bash, many commands that involve installing software, changing important settings or modifying key system files will require you to log-in as an administrator or enter an administrator password before proceeding (even if you are already logged in as an administrator in your normal graphical session).\n",
- "\n",
- "## Anatomy of a command\n",
- "\n",
- "A command has the structure \"command options arguments\". The command is a program we'd like to run, or an action we'd like to take. For example, if I open my terminal and simply type firefox, then it opens my web browser. Many commands and programs run inside the terminal, unlike Firefox. Options are things we can add to change the way the command works, often beginning with a - or --, and then a letter or word (for example, it is common in Bash that to get help for using a program, you follow the name of the command with --help e.g firefox --help gives more information about how to use the firefox command). Finally, the arguments are inputs to a command.\n",
- "\n",
- "As an example, a very simple Bash program called cat can be used to show the contents of a text file in the terminal window. If I just type cat, then the program waits for me to type some text for it to display. If I type cat A_FILE_NAME, then the contents of that file will be displayed: the file name is an argument, an input to the program. Finally, as an example of using it with an option, cat --number A_FILE_NAME. This will display the contents of a file with line numbers shown.\n",
- "\n",
- "Please see the picture below; the output of the command is not important (I'm just displaying the contents of a file).\n",
- "\n",
- "\n",
- "\n",
- "You can usually see what the options are for a program by running PROGRAM_NAME --help or running man PROGRAM_NAME, that is, the program \"manuals\" with the name of the program you want help with as an argument."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## The working directory\n",
- "\n",
- "The first command we will learn is pwd, which stands for \"print working directory\". The working directory is the folder in your computer that you are currently \"in\", just like on a graphical file browser (My Computer, Finder, nautilus, etc), you are usually viewing and manipulating the contents of just one folder.\n",
- "\n",
- "For instance, when I open my terminal and type pwd, I have something like:"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "$ pwd\n",
- "/home/sam"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This shows us where we currently are in our computer's file system. The natural thing to want to do is to view the contents of the current working directory. Just type ls, which is short for \"list\", if I'm not mistaken. Now you should see the contents of the current directory, possibly with colour coding to show different kinds of file if your terminal emulator is fancy enough."
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "$ ls\n",
- "Desktop Pictures\n",
- "Documents Public\n",
- "Downloads Templates\n",
- "Music Videos"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Cool, so now we are starting to orientate ourselves in our computer. In Bash, there are many useful options for ls. For example, ls -a is \"list all\", which shows hidden files (usually files containing settings for programs, which you will only edit occasionally and otherwise get in the way. Hidden files start with a .). You can use ls -l for a more detailed list with file sizes and such. Options that are of one letter can often be joined into one option, so ls -l -a can be ls -la, which will display a detailed list of all the files in your directory.\n",
- "\n",
- "If you provide a path to a directory to ls as an argument, it will list the contents of that directory instead:"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "$ ls Documents\n",
- "Personal\n",
- "Work\n",
- "Articles\n",
- "Letters"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Changing directory\n",
- "\n",
- "Now we learn how to navigate. The command cd, when given a directory as an argument, will change the current working directory. Example:"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "$ pwd\n",
- "/home/sam\n",
- "$ cd Documents\n",
- "$ pwd\n",
- "/home/sam/Documents"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You can go \"up\" a directory by navigating to ..:"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "$ pwd\n",
- "/home/sam\n",
- "$ cd Documents\n",
- "$ pwd\n",
- "/home/sam/Documents\n",
- "$ cd ..\n",
- "$ pwd\n",
- "/home/sam"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "If you need to refer to a folder or file with spaces in, put the file name in quote marks, for example cd \"My Documents\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Relative and absolute paths\n",
- "\n",
- "So far, we have used relative file paths. This is where the \"route\" taken to the desired directory or file is relative to the current working directory. In the above example, cd Documents took me to Documents because Documents is contained in the current working directory. If my current working directory were, say, home/sam/Pictures, then to navigate to the Documents directory in one move, I could use cd ../Documents, meaning \"go up one level, and then go to Documents\".\n",
- "\n",
- "However, I can also use what is called an absolute path. This is an exact address, always referring to the same file or directory regardless of the current working directory. In Mac OSX/Linux, starting a path with / makes it absolute. Hence if I am in the Pictures folder (or indeed ANY folder) and want to go to Documents, I can always type"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "$ cd /home/sam/Documents\n",
- "$ pwd\n",
- "/home/sam/Documents"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "On Windows Powershell, you can give an absolute path by starting the path with the drive name, like"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "> cd C:\\Users\\Sam\\Documents"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Making a new directory\n",
- "\n",
- "The command to make a new directory is mkdir, and the directory name is provided as an argument:"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "$ ls\n",
- "Desktop Pictures\n",
- "Documents Public\n",
- "Downloads Templates\n",
- "Music Videos\n",
- "$ mkdir python-scripts\n",
- "$ ls\n",
- "Desktop python-scripts\n",
- "Documents Public\n",
- "Downloads Templates\n",
- "Music Videos\n",
- "Pictures "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Note that I chose to use a - instead of a space in my directory name. As a regular user of the command line, this makes it easier to type as I don't have to remember to put it in quotes this way."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Tab completion\n",
- "\n",
- "One of the nicest features about modern command-lines is that they often allow tab completion. Pressing the TAB key when partway through a command or file in the current directory will complete the command for you, if there is only one possibility. For example, in my /home/sam directory, typing cd Doc and hitting TAB will complete the command to cd Documents. This allows for much more rapid navigation and manipulation.\n",
- "\n",
- "## Move, copy, or rename a file\n",
- "\n",
- "It may surprise you that on the command-line, moving and renaming files are the very same command. It's quite simple really. The mv command takes two arguments: the first, a source file; the second, a target. If the target is a directory, the file is moved to that directory. If the target is not a directory, then the source file is renamed to whatever you set target to. For example, if I have a file called my-file in the home folder, and I wish to move it to Documents, I just type mv my-file Documents. If I want to renamed the file to, say, \"my-file2\", I type. mv my-file my-file2.\n",
- "\n",
- "The copy command, cp works in basically the same way. Let's say my-file contains some software settings that I want to tinker with without risking breaking anything. I should backup the file so I can restore it if I do something wrong. So, cp my-file my-file-backup will create a copy of that file called my-file-backup."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Delete a file\n",
- "\n",
- "Delete a file with the command rm, followed by the name of the file relative to the current working directory. If you want to delete a folder, you will have to use rm -r DIRECTORY_NAME. This -r stands for \"recursive\" and means \"delete the contents and the folder\"."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Make a new text file\n",
- "\n",
- "In bash, you can use the command nano followed by a file name (if it doesn't exist it will be created) to open the nano text editor, an easy-to-use terminal-based text editor. Here you can type a Python file, or any other text file you like. The basic commands are given at the bottom (the ^ sign refers to the ctrl key, so to save (\"write out\") a file is ctrl+O. The text editor has syntax highlighting based on the file name, so ending the file name with .py will enable Python highlighting; in other words, the colours will change to reflect the structure of Python code, if you terminal supports colours.\n",
- "\n",
- "nano isn't the best text editor out there, but it's quick and easy to use if you just need to slightly modify a file while you browse on the command-line.\n",
- "\n",
- "\n",
- "\n",
- "On Windows Powershell, you can use notepad.exe FILENAME to achieve a similar end."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Access Python\n",
- "\n",
- "Well, now we get to the business end. You know how to navigate through your computer and even write a Python program using nano. If Python is installed correctly, and your shell knows where it is, typing python should open the interactive Python interpreter, a command-line interface with a shell that understands Python commands, rather than Bash or Powershell commands. You should see something like this. The >>> means it is ready to start interpreting Python commands."
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "$ python\n",
- "Python 3.6.1 |Anaconda 4.4.0 (64-bit)| (default, May 11 2017, 13:09:58) \n",
- "Type \"copyright\", \"credits\" or \"license\" for more information.\n",
- ">>>"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "From here, we can type any valid Python code and the program will run it. Since we don't know any Python yet, just test it by asking it \"2 + 2\":"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- ">>> 2 + 2\n",
- "4"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now we can leave by typing exit().\n",
- "\n",
- "Next we'll learn how to run a Python program that you have already written. Type nano hello.py or notepad.exe hello.py. This has made a new Python file. In the file, write"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "print(\"Hello world!\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "and save it (ctrl+O in nano), then exit (ctrl+X in nano). This program, if written correctly, will write \"Hello world!\" on the screen.\n",
- "\n",
- "Then, when in the working directory in which you saved the file, type:"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "$ python hello.py\n",
- "Hello world!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Hence, python is the program, and hello.py is the argument provided. Now you know how to run any Python file, even one you have downloaded from the Internet.\n",
- "\n",
- "### Did you get an error when you typed python, even though you installed it fine?\n",
- "\n",
- "It means that python is not in your shell's PATH variable. Don't worry. The idea is, when you type a command, it would be very slow (and risky) for the shell to just search your entire computer for some program that command could refer to. Instead, there is a list called PATH of places the shell should look to find programs.\n",
- "\n",
- "So, to solve this, you must find where you have installed Python, and then tell your computer that it's okay to look here when you give it a command.\n",
- "\n",
- "If you're using Bash:\n",
- "1. Navigate to your home folder. The quick way is cd ~, since ~ always refers to your home folder, for convenience.\n",
- "2. You need to edit a file called .bashrc. The ., recall, means it is a hidden file. This is just a file that contains settings for your Bash sessions.\n",
- "3. Hence, type nano .bashrc. There might already be a bunch of stuff in here. If you're feeling bored but brave sometime, feel free to back up this file and have a play around to see what happens.\n",
- "4. Scroll down to the bottom of the file. Add the line:\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "export PATH=\"/path/to/folder/where/python/is/installed:$PATH\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This just means \"change the PATH variable to '/path/to/where/python/is/installed' followed by whatever the PATH variable was before\". Save the file and exit, then type exit into Bash. Open the terminal again and Python should work.\n",
- "\n",
- "If you're using Windows Powershell\n",
- "\n",
- "Type into Powershell\n",
- "\n",
- "[Environment]::SetEnvironmentVariable(\"Path\", \"$env:Path;C:\\path\\to\\folder\\where\\python\\is\\installed\")\n",
- "\n",
- "This should solve it.\n",
- "\n",
- "If neither of these work, I'm afraid you'll have to get your Google-fu on."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Still a bit baffled? Check out the video\n",
- "\n",
- "All of these basic commands are demonstrated in the video below. You'll see that it's pretty easy once you get going.\n",
- "\n",
- "\n",
- "If you're interested in learning more about how to use Bash and become a command-line expert, there's a great free e-book called The Linux Command Line by William E. Shotts Jr."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- " \n",
- " "
- ],
- "text/plain": [
- ""
- ]
- },
- "execution_count": 1,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "from IPython.display import YouTubeVideo\n",
- "YouTubeVideo(\"poUKA4pOn7k\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Exercise\n",
- "\n",
- "From the command line, create a folder in your home directory for \"Python-and-computer-notes\" or something. In here, use the nano text editor to write a short summary of everything you learned here, and save it for future reference."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.1"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/PurePy 6. Strings and Text/.ipynb_checkpoints/6.0 Working with text-checkpoint.ipynb b/PurePy 6. Strings and Text/.ipynb_checkpoints/6.0 Working with text-checkpoint.ipynb
deleted file mode 100644
index dcc45f4..0000000
--- a/PurePy 6. Strings and Text/.ipynb_checkpoints/6.0 Working with text-checkpoint.ipynb
+++ /dev/null
@@ -1,1049 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Strings\n",
- "\n",
- "String manipulation is widely regarded as one of Python's strong points. These segments of text contain many rich features, and it is straightforward in Python to pull strings apart and re-combine them in interesting ways.\n",
- "\n",
- "Working with strings is an important skill in Python. For one, reading data into a program will often take the form of a file containing text, and so we must be proficient in extracting the bits we're interested in. Moreover, we are humans. We do not want the computer to merely spit out a list of numbers after performing a calculation; we want our outputs presented in a way that we can actually read.\n",
- "\n",
- "Strings are an immutable data type. The operations we perform involve forging new strings from old, rather than modifying the original string.\n",
- "\n",
- "## Slicing and dicing\n",
- "\n",
- "To get a \"slice\" of a string is similar to getting an item from a list (in fact we can also get slices of lists by the same syntax). However, we specify a start and end index, rather than just an index:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "a piece \n"
- ]
- }
- ],
- "source": [
- "a_string = \"This is a piece of string\"\n",
- "print(a_string[8:16])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can also leave one end \"open\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "This\n",
- "is a piece of string\n"
- ]
- }
- ],
- "source": [
- "print(a_string[:4])\n",
- "print(a_string[5:])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To get the last x letters, we can count backwards with negative numbers:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "string\n"
- ]
- }
- ],
- "source": [
- "print(a_string[-6:]) # will get the last 6 letters!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Strings can be concatenated (joined together) using the addition operator:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Hallo Welt\n"
- ]
- }
- ],
- "source": [
- "print(\"Hallo \" + \"Welt\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "If we wish to use this technique to include, for instance, numbers, then we must first convert the number into a string, as + has a different meaning for strings and numbers."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "The year is 2017!\n"
- ]
- }
- ],
- "source": [
- "year = 2017\n",
- "print(\"The year is \" + str(year) + \"!\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "These tools already provide a flexible system for string manipulation. Many of the functions that work on sequence-like data will also work on strings. For instance:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "30\n"
- ]
- }
- ],
- "source": [
- "print(len(\"How long is a piece of string?\"))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "['A', ' ', 'l', 'i', 's', 't', ' ', 'o', 'f', ' ', 'l', 'e', 't', 't', 'e', 'r', 's']\n"
- ]
- }
- ],
- "source": [
- "print(list(\"A list of letters\"))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Special characters and escape sequences\n",
- "\n",
- "Certain special characters are represented with a backslash followed by a letter, called an escape sequence. Python considers this pairing to be a single character, even though it looks like two characters on the screen. For example, a new line is represented with \\n."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Split a string\n",
- "onto two lines\n"
- ]
- }
- ],
- "source": [
- "print(\"Split a string\\nonto two lines\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Escape sequences also allow you to use quotation marks inside a string without Python thinking you are closing the string. Finally, if you actually do want to insert a backslash, then \\\\\\ is the escape sequence to insert a backslash.\n",
- "\n",
- "A full list of escape sequences can be found here http://www.techpaste.com/2014/06/escape-sequences-python/. Probably you don't know what all of these do. Neither do I. Why not try some out anyway?"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Formatting strings\n",
- "\n",
- "Many languages, such as C and its derivatives, allow a segment of text to receive inputs using a funny looking syntax in which % signs appear everywhere. Python supports this syntax, and in Python 2 this was the preferred way to modify strings. In Python 3, however, we have the more powerful .format() ability.\n",
- "\n",
- "Have a good look at this section, as it provides the ideal tools for giving useful, readable outputs. However, string formatting is virtually its own mini-langauge, and is a lot to take in at once. The important thing is to know that Python can do all these things. You can work out the details as and when you need them.\n",
- "\n",
- "The most basic use of string formatting is to insert data from your program into a string. This can be any data that has a suitable string representation, such as numbers. There are many options for doing this. The first is simply by position:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "As I was going to St. Ives I met a man with 7 wives\n"
- ]
- }
- ],
- "source": [
- "destination = \"St. Ives\"\n",
- "wivescount = 7\n",
- "poem = \"As I was going to {} I met a man with {} wives\".format(destination, wivescount)\n",
- "print(poem)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Notice that we have two {}s and provide two arguments to the format function. The order that we provide the arguments is the order that they appear in the text. We can reference the arguments more explicitly by including the position (this is useful if the same argument will appear several times:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "As I was going to St. Ives I met a man with 7 wives,\n",
- "those 7 wives had 7 sacks.\n"
- ]
- }
- ],
- "source": [
- "poem = \"\"\"As I was going to {0} I met a man with {1} wives,\n",
- "those {1} wives had {1} sacks.\"\"\".format(destination, wivescount) # triple quotes allow multi-line paragraphs\n",
- "print(poem)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "So here we can see the zero'th argument is referenced once; the one'th argument appears 3 times. If we don't want to worry about position, we can use keyword arguments:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Those 7 sacks had 7 cats\n"
- ]
- }
- ],
- "source": [
- "poem = \"\"\"Those {count} sacks had {count} {animals}\"\"\".format(animals=\"cats\", count=wivescount)\n",
- "print(poem)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can supply .format() with any data structure, and access its items in the usual way:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 21,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "kits, cats, sacks and wives, how many going to St. Ives?\n"
- ]
- }
- ],
- "source": [
- "travellers = [\"wives\", \"sacks\", \"cats\", \"kits\"]\n",
- "# access list items\n",
- "poem = \"{0[3]}, {0[2]}, {0[1]} and {0[0]}, how many going to {1}?\".format(travellers, destination)\n",
- "print(poem)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- ".format() also provides ways to represent floats and large integers."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 24,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "There were 23,455,453,424 travellers to St. Ives\n"
- ]
- }
- ],
- "source": [
- "large_int = 23455453424\n",
- "print(\"There were {0:,} travellers to {1}\".format(large_int, destination))\n",
- "# :, adds comma as thousands separator."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 39,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "That answer is 8370968.388294 times too big!\n",
- "That answer is 8370968.39 times too big!\n",
- "That answer is 8,370,968.39 times too big!\n"
- ]
- }
- ],
- "source": [
- "correct_answer = 2802\n",
- "rebuke = \"That answer is {0:f} times too big!\".format(large_int/correct_answer)\n",
- "# default (6 decimal places)\n",
- "print(rebuke)\n",
- "rebuke = \"That answer is {0:.2f} times too big!\".format(large_int/correct_answer)\n",
- "print(rebuke)\n",
- "# two decimal places\n",
- "rebuke = \"That answer is {0:,.2f} times too big!\".format(large_int/correct_answer)\n",
- "print(rebuke)\n",
- "# two decimal places and comma separators"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Yet another use for string formatting is in aligning text. Text can be left-aligned, right-aligned, or centered. Let's place 3 words on separate lines, with line-width of 30 characters, each with a different alignment:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 36,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "right \n",
- " left\n",
- " center \n"
- ]
- }
- ],
- "source": [
- "print( \"{:<30}\\n{:>30}\\n{:^30}\".format(\"right\", \"left\", \"center\") )"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "So, this is no more mysterious than \"{}\\n{}\\n{}\", but we use the <, >, ^ characters to show alignment followed by the linewidth."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## More ways to carve up strings\n",
- "\n",
- "In the Data Structures example video, we met a function called partition() that splits up a string if you provide it with a separator character. There are many many functions on strings that perform similar tasks.\n",
- "\n",
- "For example, we have splitting and joining, which allow easy conversion from lists to strings and strings to list. A string can be split into indvidual words using the split() function:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 40,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "['These', 'words', 'will', 'form', 'a', 'list']\n"
- ]
- }
- ],
- "source": [
- "listofwords = \"These words will form a list\".split()\n",
- "print(listofwords)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Split also will take an argument to specify a different delimiter.\n",
- "\n",
- "The counter to this is join(), which acts on the character you wish to use a separator, and takes a list as its arguments. This is a faster algorithm for gluing together a bunch of words than repeated use of the + operator, and it can easily be combined with a list comprehension, too."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 42,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Hello\n"
- ]
- }
- ],
- "source": [
- "# just straight up join, good for making a word\n",
- "# we here use join on an empty string to glue the letters directly\n",
- "word = \"\".join(['H', 'e', 'l', 'l', 'o'])\n",
- "print(word)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 43,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "These words will form a list\n"
- ]
- }
- ],
- "source": [
- "# here we use join with spaces to separate, making a sentence\n",
- "reunited_words = \" \".join(listofwords)\n",
- "print(reunited_words)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 46,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Bread,\n",
- "Bananas,\n",
- "Beans,\n",
- "Beer\n"
- ]
- }
- ],
- "source": [
- "# more complicated example. the joining string here is a comma followed by new line\n",
- "# we also use a list comprehension to capitalize each item in the list\n",
- "\n",
- "shopping_list = ['bread', 'bananas', 'beans', 'beer']\n",
- "readable_shopping = \",\\n\".join([item.capitalize() for item in shopping_list])\n",
- "print(readable_shopping)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Cutting off the beginning or end of a line; the string module\n",
- "\n",
- "It is somewhat common when working with strings to wish to remove a chunk of text from the beginning or end of a line. As an example, suppose I have copied and pasted a numbered list from the internet, and I wish to remove the numbers. The trouble is, the numbers have different numbers of digits, so I can't just do a straight up slice on each line."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 52,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "best_python_books = \"\"\"1. Dive Into Python 3\n",
- "2. Automate The Boring Stuff With Python\n",
- "3. Python For Everyone\n",
- "4. Python Cookbook, 3rd Ed\n",
- "5. Python For Data Analysis\n",
- "6. Fluent Python\n",
- "7. Violent Python\n",
- "8. Think Python\n",
- "9. Learn Python The Hard Way\n",
- "10. Problem Solving with Algorithms and Data Structures Using Python\n",
- "11. Python Crash Course\n",
- "\"\"\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The tool that comes to our rescue is .strip(), which takes as its argument a collection of characters as a string. Python will remove those characters from the beginning of a string, until it reaches a character not contained in the argument. If we give it no argument, it just removes whitespace (spaces and tabs). To break the list into separate lines, we'll use .splitlines(), which is like split, but splits at linebreaks."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 53,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "['1. Dive Into Python 3', '2. Automate The Boring Stuff With Python', '3. Python For Everyone', '4. Python Cookbook, 3rd Ed', '5. Python For Data Analysis', '6. Fluent Python', '7. Violent Python', '8. Think Python', '9. Learn Python The Hard Way', '10. Problem Solving with Algorithms and Data Structures Using Python', '11. Python Crash Course']\n"
- ]
- }
- ],
- "source": [
- "lines = best_python_books.splitlines()\n",
- "print(lines)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now we need to remove the leading characters. Python provides a useful module called string in its standard library, that contains lots of useful strings, as well as additional functions for working with strings. We want to remove the numbers at the start, so we can say:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 55,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "0123456789\n"
- ]
- }
- ],
- "source": [
- "import string # gives us a string containing all the numbers\n",
- "print(string.digits)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "While this actually requires more keystrokes than simply writing the numbers \"0123456789\", the string module contains many other collections of characters like this such as punctuation"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 56,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~\n"
- ]
- }
- ],
- "source": [
- "print(string.punctuation)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 58,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\n"
- ]
- }
- ],
- "source": [
- "print(string.ascii_letters)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "These strings are useful for checking facts about other strings. For example, this snippet will check if there is any punctuation in a string:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 59,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n",
- "True\n"
- ]
- }
- ],
- "source": [
- "def has_punc(text):\n",
- " import string\n",
- " for c in string.punctuation:\n",
- " if c in text:\n",
- " return True\n",
- " return False\n",
- "\n",
- "print( has_punc(\"Has no punctuation\") )\n",
- "print( has_punc(\"Has punctuation.\"))\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Anyway, back to our problem. We want to remove the numbers, full stops and whitespace from the strings in the list. Here we go:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 64,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Dive Into Python\n",
- "Automate The Boring Stuff With Python\n",
- "Python For Everyone\n",
- "Python Cookbook, 3rd Ed\n",
- "Python For Data Analysis\n",
- "Fluent Python\n",
- "Violent Python\n",
- "Think Python\n",
- "Learn Python The Hard Way\n",
- "Problem Solving with Algorithms and Data Structures Using Python\n",
- "Python Crash Course\n"
- ]
- }
- ],
- "source": [
- "chars_to_remove = \". \" + string.digits # make a string containing all bad chars\n",
- "\n",
- "nice_list = [book.strip(chars_to_remove) for book in lines]\n",
- "\n",
- "readable_list = \"\\n\".join(nice_list)\n",
- "\n",
- "print(readable_list)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Clearly, to use strip(), we have to be pretty confident about the format of our data. If I had a book called \"20 Cool Python Programs\" in the list, then the \"20\" part would have been stripped out as well.\n",
- "\n",
- "## Some quick transformations of strings\n",
- "\n",
- "The developers of Python kindly include many single word ways to make quick adjustments to strings. We just demonstrate a bunch of them here; their functioning should be self explanatory:\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 68,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Some advanced string theory\n",
- "some advanced string theory\n",
- "SOME ADVANCED STRING THEORY\n",
- "sOME ADVANCED STRING THEORY\n",
- "Some Advanced String Theory\n",
- "Some basic string theory\n"
- ]
- }
- ],
- "source": [
- "my_string = \"Some advanced string theory\"\n",
- "\n",
- "print(my_string.capitalize())\n",
- "print(my_string.lower())\n",
- "print(my_string.upper())\n",
- "print(my_string.swapcase())\n",
- "print(my_string.title())\n",
- "print(my_string.replace(\"advanced\", \"basic\"))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You can read more about how to use strings here\n",
- "https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str\n",
- "and about the string module here\n",
- "https://docs.python.org/3/library/string.html"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": true
- },
- "source": [
- "# Text\n",
- "\n",
- "You may be looking at the title of this section and thinking \"wait, haven't we just learned all about text?\". And the answer is yes... sort of. We've been learning about how to work with text inside Python. We've just been willy-nilly writing some strings and slicing them up. What we have not talked about, and is unfortunately an important thing to be aware of, is text that is out there in the wild.\n",
- "\n",
- "## The bad news\n",
- "\n",
- "Some terminology first. A character is the abstract meaning behind the little squiggles you see on the screen that form text. The squiggles themselves are called \"glyphs\". However, the glyphs cannot be the characters, since in different fonts, the same character can be represented by two very different glyphs. So for instance, the character that is \"the first uppercase letter of the latin alphabet and sounds like 'ey'\" is represented by the glyph \"A\". We don't need to worry about glyphs, since this is determined by the font of our computer, not our program.\n",
- "\n",
- "When we work with text in Python, we just see the strings as \"a sequence of characters\". This is great, and is exactly how you should think of strings when you manipulate them in Python. Trouble is, computers do not store characters; they store numbers written in binary. This means there is a natural problem of deciding which characters correspond to which numbers.\n",
- "\n",
- "Probably you've not encountered this problem in any meaningful way before. You may have stumbled across webpages with some missing or incorrect characters. But in your life, you've mostly been working with word processed documents, in a familiar word processor, written using characters native to your language. Or you've been using webpages via web-browsers built by people who understand this problem and have essentially solved it for you.\n",
- "\n",
- "Back in the days of yore, computer users mostly just shared software around their own universities and workplaces, at the very least within their own country. This means that lots of different character encodings sprang up -- methods for turning the bytes (numbers) in a file into text on the screen. In the UK and US, the common solution was ASCII encoding, which due to our relatively small alphabet meant that each character could be stored in a single byte as a number between 0 and 127.\n",
- "\n",
- "These days, there is something called the internet, which means that text is now flying all over the world, from the US, which uses only a few characters; to Europe, which uses more because of all the accents; to Greece, Russia, and Middle East, which have different alphabets; to China, which has literally thousands of characters. Also, in the 21st century, there are emojis.\n",
- "\n",
- "So if you're planning on interacting with text that comes from a source outside of your own computer, you might run into problems.\n",
- "\n",
- "## Unicode\n",
- "\n",
- "Unicode is a system for organizing the characters of the world, as well as a set of standards for encoding these characters. In a nutshell, each character is assigned to a unicode \"code point\", usually written in . For instance the letter \"A\" is \"0041\". This is not an encoding, but merely an organization method. At least now we can organize the characters of the world into some kind of coherent structure, a bit like a periodic table of elements but for text. According to Wikipedia, the current version of unicode contains 136,755 characters from 139 writing systems, plus additional symbols that are not from any particular writing system, such as emoji. When you create a string in Python, it is considered to be a sequence of unicode code points.\n",
- "\n",
- "Note that unicode code points are generally given in hexadecimal. This is simply a way of writing down numbers using 16 symbols instead of the usual ten (or two, in binary), meaning larger numbers can be written using fewer digits. Since we have only ten numerals, letters are used instead; the numerals used in hexadecimal are 0123456789ABCDEF. E is fourteen, F is fifteen. 10 is sixteen, 11 is seventeen, all the way to FF, which is 255 in decimal, and then we start again with 100. This is just a way to shorten long numbers in binary -- each hex digit corresponds to 4 binary digits (bits), meaning that a byte is represented by two hex digits. There's rarely any need to do arithmetic with hex-reperesented numbers, or figure out what the decimal/binary representation is. Just be aware that when you see, say, \"A3\" when discussing a unicode code point, it is actually a number.\n",
- "\n",
- "There remains the question then of how to encode these characters into bytes. Unicode has several possible standards. The reason for different standards is that European computer users, say, whose languages' characters could be stored in 2 bytes, did not want to have to use additional bytes to store all the Chinese characters they seldom used, for example by allocating 4 bytes per character. By having different encoding systems, we've solved one problem, but it's very not flexible. What about times when we need those occasional Chinese characters? What about emoji?\n",
- "\n",
- "Then two bright sparks, Ken Thompson and Rob Pike, came up with a new encoding system called UTF-8. In their system the number of bytes per character could vary. The standard ASCII characters, for example, could be stored as 1 byte. Accented characters, 2 bytes. 3 bytes is enough to store all the Chinese characters. Other, uncommon symbols, such as emoji, are relegated to taking up 4 bytes. And all of these can co-exist within the same file. There's no need to switch encoding midway through. In theory, it \"just works\".\n",
- "\n",
- "There is a price to pay, as with most nice things in life. For a program to search through UTF-8 encoded text now takes longer, because it can't count on each of the characters being the same length (in terms of digits); it has to check each byte separately to see when one character ends and the next begins.\n",
- "\n",
- "Nonetheless, UTF-8 is now the standard encoding on the web, accounting for 90% of websites. The Python interpreter expects Python files to be written in UTF-8. Python \"just works\" when it reads UTF-8 encoded text.\n",
- "\n",
- "\n",
- "## The good news\n",
- "\n",
- "Working with these different encodings in Python is actually fairly straightforward for the most part. Your mission when working with text in Python should be to convert it to a string as soon as is possible. In string form, you are working directly with characters -- that is to say, unicode code points, and don't have to worry about what these characters are actually stored as in memory.\n",
- "\n",
- "The two functions you need are str.encode() and bytes.decode() (where str and bytes are the snippet you want to en-/decode. The argument taken is the name of the encoding to be used, given as a string -- the default encoding is UTF-8."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Sam\n",
- "\n"
- ]
- }
- ],
- "source": [
- "my_name = \"Sam\"\n",
- "my_name_as_bytes = my_name.encode()\n",
- "print(type(my_name_as_bytes))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "If we print my_name_as_bytes, what do we get?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "b'Sam'\n"
- ]
- }
- ],
- "source": [
- "print(my_name_as_bytes)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "It looks the same, but with a little b at the beginning. But it is certainly not the same. These are no longer characters, but representations of sequences of bytes. Confused?\n",
- "\n",
- "Here is what is going on. There is some good news here, actually: the most commonly used characters in English form part of the ASCII character set, which if we recall stores each character as a number between 0 and 127. One of the clever aspects of UTF-8 encoding is that the encodings for these particular characters are identical to their ASCII encodings. You can open a file written in ASCII using an UTF-8 decoding algorithm and you wouldn't know the difference.\n",
- "\n",
- "Now, when Python represents a sequence of bytes, rather than give you a sequence of numbers, it represents each byte with an ASCII character, as this is usually easier to interpret. Because the letters of Sam are in the ASCII character set, this is no problem! However, the same cannot be said for another string, for example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "b'This jacket costs \\xc2\\xa330'\n"
- ]
- }
- ],
- "source": [
- "jacket = \"This jacket costs £30\"\n",
- "jacket_as_bytes = jacket.encode()\n",
- "print(jacket_as_bytes)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now we can see £ sign has a strange representation, because this character is not ASCII (owing to the fact that ASCII is an American standard, so only the dollar sign is part of the system). \\x just means \"heXadecimal\". In other words, these numbers don't have an ASCII representation, so they are given as their hex values instead, and the \\x makes us aware of this.\n",
- "\n",
- "However, this is still valid UTF-8 bytes, and a program reading these bytes as UTF-8 can recover the original:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "This jacket costs £30\n"
- ]
- }
- ],
- "source": [
- "print(jacket_as_bytes.decode('UTF-8'))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Tada! So what happens if we try to encode the last string as ASCII?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "ename": "UnicodeEncodeError",
- "evalue": "'ascii' codec can't encode character '\\xa3' in position 18: ordinal not in range(128)",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mUnicodeEncodeError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mjacket\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mencode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'ASCII'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;31mUnicodeEncodeError\u001b[0m: 'ascii' codec can't encode character '\\xa3' in position 18: ordinal not in range(128)"
- ]
- }
- ],
- "source": [
- "print(jacket.encode('ASCII'))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We get an error, because the £ sign simply has no corresponding ASCII number.\n",
- "\n",
- "So, soon we'll be looking at how to open a (text) file in Python. How do we know how to decode the text? In general, sadly, we don't. For files that use one of the unicode encodings, the file may have a so called byte-order mark (BOM) at the beginning containing 2 or 3 bytes which indicate the encoding used (though it also might not -- more information on that here http://codesnipers.com/?q=node/68). Other than that, you may have to use some trial and error. Presuming you have a rough idea of what the file should look like when decoded, you could write a loop that tries some different encodings for you. Finally, included with Anaconda is a library that will attempt to determine the encoding for you. We demonstrate its usage here. Let's first create a string with some non-ASCII characters in:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Here I have taken a paragraph from a French newspaper, containing some accented characters\n",
- "french_paragraph = \"Vite, de l'ombre ! Un pic de chaleur est attendu en France mardi, selon les instituts météorologiques, qui tablaient la veille sur des températures allant jusqu'à... 38°C ! «On assiste à une dépression sur le proche Atlantique, décrypte Frédéric Decker, météorologue chez MeteoNews. Celui-ci va avoir un effet de pompe à chaleur en faisant remonter de l'air en provenance d'Espagne et du Maghreb.»\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now we will encode it into some different formats:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 22,
- "metadata": {},
- "outputs": [],
- "source": [
- "encodings = ['UTF-8', 'UTF-16', 'ISO-8859-1', 'macintosh']\n",
- "french_bytes = {}\n",
- "for code in encodings:\n",
- " french_bytes[code] = french_paragraph.encode(code)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now to see if the library is able to have a good guess at how this paragraph has been encoded:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 28,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "{'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}\n",
- "Correct answer is UTF-8. chardet's guess is: utf-8\n",
- "{'encoding': 'UTF-16', 'confidence': 1.0, 'language': ''}\n",
- "Correct answer is UTF-16. chardet's guess is: UTF-16\n",
- "{'encoding': 'ISO-8859-1', 'confidence': 0.73, 'language': ''}\n",
- "Correct answer is ISO-8859-1. chardet's guess is: ISO-8859-1\n",
- "{'encoding': 'Windows-1254', 'confidence': 0.5840197866395126, 'language': 'Turkish'}\n",
- "Correct answer is macintosh. chardet's guess is: Windows-1254\n"
- ]
- }
- ],
- "source": [
- "import chardet\n",
- "\n",
- "# the dictionary.items() function gives tuples of key-value pairs\n",
- "for truecode, byte_string in french_bytes.items():\n",
- " # chardet.detect() will make this library attempt to guess \n",
- " guess = chardet.detect(byte_string)['encoding']\n",
- " print(chardet.detect(byte_string))\n",
- " print(\"Correct answer is {}. chardet's guess is: {}\".format(truecode, guess))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "So it managed to correctly guess 3/4 encodings. The moral is that this library can help you out, but you mustn't trust it blindly!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.1"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 1
-}
diff --git a/PurePy 7. Importing Data/.ipynb_checkpoints/7.1 Opening Files-checkpoint.ipynb b/PurePy 7. Importing Data/.ipynb_checkpoints/7.1 Opening Files-checkpoint.ipynb
deleted file mode 100644
index 0a72d6e..0000000
--- a/PurePy 7. Importing Data/.ipynb_checkpoints/7.1 Opening Files-checkpoint.ipynb
+++ /dev/null
@@ -1,469 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Opening files\n",
- "\n",
- "When we're writing a program, it's pretty clear that we don't want to always have to type the data we're working with directly into the source code. Rather, we want to get the data from an external source: either the web, or a file on our computer. In this article, we're going to look at how to work with files in Python.\n",
- "\n",
- "Did you read the article about string manipulation, and in particular, the bit about character encodings? It might be helpful here!\n",
- "\n",
- "## The open() function and its modes\n",
- "\n",
- "Python has one built-in function for getting the information out of a file, or writing information to a file. \n",
- "\n",
- "This is simply the open() function. Its first argument is always a string, which is the path to a file.\n",
- "\n",
- "If you checked out the lesson on using the command line (and if you haven't you really should!), the way that file paths work should be very familiar. They can be either relative or absolute. Relative to what? Well, Python has a current working directory, just like you do when you are working via the command line. This will default to the current working directory you were in when you ran Python. Finally, in Python you should always use forward slashes in file paths, even if your computer uses backslashes. The open() function is smart and will figure this out for you -- it means the same code can easily open files on different operating systems!\n",
- "\n",
- "What happens next is dependent on the next argument: the mode. This will determine whether the file should be opened as text or as bytes, and whether you want to read the file or write to the file. We'll deal with these modes now.\n",
- "\n",
- "The function returns a file object, which you should store as a variable to refer to later (otherwise the file will be opened but you won't be able to access it).\n",
- "\n",
- "### Read mode, 'r'\n",
- "\n",
- "This is the mode you need to get the data out of a file as text; it is the default mode when opening. By default, it attempts to decode the file using the default encoding of your computer. For instance, a Windows computer and a Linux machine may have different default encodings. To be safe, it's best to specify the correct encoding by passing the keyword argument encoding. \n",
- "\n",
- "Let's open a text file and read its contents."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "example_file = open('haiku.txt', 'r', encoding='UTF-8')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What can we do with this file? Well, we can try to extract its contents as a string, using .read()."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "contents = example_file.read()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "This is a text file,\n",
- "UTF-8 encoding.\n",
- "It has two line breaks.\n"
- ]
- }
- ],
- "source": [
- "print(contents)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What happens if we try to read it again?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "contents2 = example_file.read()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n"
- ]
- }
- ],
- "source": [
- "print(contents2)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Nothing! What happened?\n",
- "\n",
- "When we read a file, you should imagine it like a tape. Just like a tape, once you have read to the end, you have to \"rewind\" it to read it again. To do this, use .seek()."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "0"
- ]
- },
- "execution_count": 14,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# go back to the 0th byte\n",
- "example_file.seek(0)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "This is a text file,\n",
- "UTF-8 encoding.\n",
- "It has two line breaks.\n"
- ]
- }
- ],
- "source": [
- "contents3 = example_file.read()\n",
- "print(contents3)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "And... it works again. Be warned though: seek() doesn't count characters! It counts bytes, and if you recall from the lesson on strings and text, UTF-8 uses a variable number of bytes to encode each character. So you can't reliably search around the text file using seek() -- you could end up \"between\" characters.\n",
- "\n",
- "This is one reason I implored in the strings lesson to convert your text into a Python string as soon as possible! Once it's a string, you're safe! You can forget all about bytes and encodings.\n",
- "\n",
- "Another nice features of the file object is that if you loop over the file object, you will get each line as a string:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "THIS IS A TEXT FILE,\n",
- "\n",
- "UTF-8 ENCODING.\n",
- "\n",
- "IT HAS TWO LINE BREAKS.\n"
- ]
- }
- ],
- "source": [
- "example_file.seek(0)\n",
- "for line in example_file:\n",
- " print(line.upper())"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Why are there line breaks in funny places? This is just because each line contains a newline (\\n) character, and each print() prints to a newline, leading to a doubling up of linebreaks.\n",
- "\n",
- "There's more good news on this front. Since different operating systems prefer different linebreak characters, the file object provided by open() is kind and clever enough to figure out where the linebreaks should be when you loop over it."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "After opening any file, it is essential to close it when you are done -- ideally as soon as you have extracted the text as a string. If a file is opened by one program, other programs cannot use it. Moreover, if your program crashes unexpectedly and you didn't close the file, it may stay hanging around in memory, clogging up your computer and remaining unavailable."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 19,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "example_file.close()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We'll soon meet a better way of closing files safely.\n",
- "\n",
- "### Write and append modes; 'w' and 'a'\n",
- "\n",
- "We now know how to get data from a file. The next task is to put data in, and we have two real choices here. Write mode will delete the contents of a file, ready to be re-written from scratch. Append mode will add to the end of the file. Let's just repeat that: write mode will delete the contents of the file to be written, so make sure you've definitely got the right file, and if in doubt, back it up. If the file does not exist, it will be created."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 23,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "new_file = open('newhaiku.txt', 'w', encoding='UTF-8')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To write into the file, we use .write()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 24,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "60"
- ]
- },
- "execution_count": 24,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "haiku = \"Always remember\\nto consider that new lines\\naren't automatic.\"\n",
- "new_file.write(haiku)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Let's write again and see what happens"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 25,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Always remember\n",
- "to consider that new lines\n",
- "aren't automatic.Always remember\n",
- "to consider that new lines\n",
- "aren't automatic.\n"
- ]
- }
- ],
- "source": [
- "new_file.write(haiku)\n",
- "new_file.close()\n",
- "file_check = open('newhaiku.txt', 'r', encoding='UTF-8')\n",
- "contents = file_check.read()\n",
- "print(contents)\n",
- "file_check.close()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Unfortunately, it looks like I forgot that new lines aren't automatic. Let's add a correctly line-broken version to the end of this file."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 26,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Always remember\n",
- "to consider that new lines\n",
- "aren't automatic.Always remember\n",
- "to consider that new lines\n",
- "aren't automatic.\n",
- "\n",
- "Always remember\n",
- "to consider that new lines\n",
- "aren't automatic.\n"
- ]
- }
- ],
- "source": [
- "haiku_file = open('newhaiku.txt', 'a', encoding='UTF-8') # 'a' for \"append\" mode\n",
- "\n",
- "haiku_file.write('\\n\\n') # two new lines\n",
- "haiku_file.write(haiku)\n",
- "haiku_file.close()\n",
- "\n",
- "file_check = open('newhaiku.txt', 'r', encoding='UTF-8')\n",
- "contents = file_check.read()\n",
- "print(contents)\n",
- "file_check.close()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "That's better.\n",
- "\n",
- "### Opening/writing things as bytes\n",
- "\n",
- "We have so far been opening files as text -- the bytes in the file are converted to strings of characters. But there are times when we might want to open the file as bytes. There are two main times we might want to do this.\n",
- "\n",
- "* The file is not a text file!\n",
- "* The file is a text file, but we don't know what the encoding is.\n",
- "\n",
- "In this latter case, we might want to open it as bytes and then use some method to try to determine the encoding, such as the chardet module from the previous topic. Opening something as bytes is just the same, but you add a b:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 28,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "b\"Always remember\\nto consider that new lines\\naren't automatic.Always remember\\nto consider that new lines\\naren't automatic.\\n\\nAlways remember\\nto consider that new lines\\naren't automatic.\"\n",
- "{'encoding': 'ascii', 'confidence': 1.0, 'language': ''}\n"
- ]
- }
- ],
- "source": [
- "bytes_file = open('newhaiku.txt', 'rb')\n",
- "print(bytes_file.read())\n",
- "import chardet\n",
- "bytes_file.seek(0)\n",
- "print(chardet.detect(bytes_file.read()))\n",
- "bytes_file.close()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This incorrect guess from chardet just confirms what we were saying last time, that UTF-8 and ASCII are identical on the ASCII characters."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## The with keyword\n",
- "\n",
- "So far, I've been drilling the importance of safely opening and closing files. But now, we're going to basically forget all that and show a better, safer way of opening files. You may have already seen it if you've been watching the videos closely. Check out this code:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 29,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "This is a text file,\n",
- "UTF-8 encoding.\n",
- "It has two line breaks.\n"
- ]
- }
- ],
- "source": [
- "with open('haiku.txt', 'r', encoding='UTF-8') as haiku:\n",
- " haiku_string = haiku.read()\n",
- " \n",
- "print(haiku_string)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "And now, I don't need to close it. In fact, it's already closed. The with block opens the file only for the duration of the code in the block, and closes it when the with block has finished executing. The best part is that this happens regardless of why the with block finished executing, even if it's caused by a crash or if most of the block is skipped by if-statements.\n",
- "\n",
- "You should use with when you open files, extract the information you need from inside the with block, and then just move on, allowing with to close the file for you to free up the resources. The syntax is simple -- the open() function works just as before. The as keyword just assigns it to a variable.\n",
- "\n",
- "This method can be used for reading and writing files, and is the safest and most \"Pythonic\" way to work with files."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.1"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/PurePy 7. Importing Data/.ipynb_checkpoints/7.2 Reading and storing data; CSV, JSON, and more-checkpoint.ipynb b/PurePy 7. Importing Data/.ipynb_checkpoints/7.2 Reading and storing data; CSV, JSON, and more-checkpoint.ipynb
deleted file mode 100644
index b154141..0000000
--- a/PurePy 7. Importing Data/.ipynb_checkpoints/7.2 Reading and storing data; CSV, JSON, and more-checkpoint.ipynb
+++ /dev/null
@@ -1,738 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "There is a natural dichotomy between data files that are easy for a computer to read, and data files that are easy for a human to read. In this article, we'll look at three common kinds of data files you are likely to encounter, are fairly human-readable, as well as being very easily manipulated in Python.\n",
- "\n",
- "## CSV files\n",
- "\n",
- "CSV is a very simple file format. The initials stand for \"comma-separated values\", and is used to encode a table of data. All spreadsheets and most databases can be exported into CSV format, and spreadsheet software such as Excel can import CSV files, so this is a nice format to be familiar with. Line-breaks (that is, \\n or \\r characters) separate the rows, and commas separate the values in each row. Well, it's a bit more lenient than that; you can choose any character to separate the values, but comma is the one that stuck around in the name for some reason. So, this is a perfectly reasonable .csv file:"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "item,price\n",
- "bread,1.50\n",
- "rice,3.00\n",
- "bananas,0.30\n",
- "applesauce,2.00"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "but so is"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "item|price\n",
- "bread|1.50\n",
- "rice|3.00\n",
- "bananas|0.30\n",
- "applesauce|2.00"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "As we should have come to expect in Python, there is a standard library module for handling .csv files, called (wait for it) csv. The two main functions offered by this module are reader() and writer(), respectively used for reading and writing csv files. Let's look at reading, first."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "['movie name', ' gross', 'IMDB rating', 'IMDB votes']\n",
- "['Captain America: Civil War', ' 1153304495', '7.9', '418614']\n",
- "['Rogue One', ' 1056057273', '7.9', '334132']\n",
- "['Finding Dory', ' 1028570889', '7.4', '161213']\n",
- "['Zootopia', ' 1023784195', '8.1', '302479']\n",
- "['The Jungle Book', ' 966550600', '7.5', '200798']\n",
- "['The Secret Life Of Pets', ' 875457937', '6.6', '124027']\n",
- "['Batman v Superman', ' 873260194', '6.7', '479880']\n",
- "['Deadpool', ' 783112979', '8.0', '637685']\n",
- "['Suicide Squad', ' 745600054', '6.2', '404862']\n",
- "['Sing', ' 632443719', '7.2', '66129']\n"
- ]
- }
- ],
- "source": [
- "import csv\n",
- "with open('topmovies.csv', encoding='UTF-8') as f: # file contains highest grossing films of 2016\n",
- " moviescsv = csv.reader(f, delimiter=',')\n",
- "\n",
- " for line in moviescsv:\n",
- " print(line)\n",
- " "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "As we can see, each line is turned into a list of strings (by default). In this use of reader, we specified a delimiter character -- the character that separates each entry. We chose a comma, although this is redundant since it is the default anyway.\n",
- "\n",
- "We can see a problem with this import. Most entries have a space following the comma, which we don't want. This is easily fixed:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "['movie name', 'gross', 'IMDB rating', 'IMDB votes']\n",
- "['Captain America: Civil War', '1153304495', '7.9', '418614']\n",
- "['Rogue One', '1056057273', '7.9', '334132']\n",
- "['Finding Dory', '1028570889', '7.4', '161213']\n",
- "['Zootopia', '1023784195', '8.1', '302479']\n",
- "['The Jungle Book', '966550600', '7.5', '200798']\n",
- "['The Secret Life Of Pets', '875457937', '6.6', '124027']\n",
- "['Batman v Superman', '873260194', '6.7', '479880']\n",
- "['Deadpool', '783112979', '8.0', '637685']\n",
- "['Suicide Squad', '745600054', '6.2', '404862']\n",
- "['Sing', '632443719', '7.2', '66129']\n"
- ]
- }
- ],
- "source": [
- "with open('topmovies.csv', encoding='UTF-8') as f:\n",
- " moviescsv = csv.reader(f, delimiter=',', skipinitialspace=True)\n",
- "\n",
- " for line in moviescsv:\n",
- " print(line)\n",
- " "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The csv.reader object provides a large number of options and fixes to get the import just right. Another consideration with csvs is \"what if the entry contains the delimiter?\" For example, what if one of the movie titles in the file I imported contained a comma? For this, we use quotes: punctuation inside quotation marks is ignored. Hence, the csv reader also allows us to specify which character is used for quoting.\n",
- "\n",
- "The csv.reader object has not created a copy of the csv file in Python's memory; it is still reading from the file. Therefore, the file must still be open when we access the lines via the reader. If we want to close the file, we should move the entries into another structure such as a list or dictionary:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[['movie name', 'gross', 'IMDB rating', 'IMDB votes'], ['Captain America: Civil War', '1153304495', '7.9', '418614'], ['Rogue One', '1056057273', '7.9', '334132'], ['Finding Dory', '1028570889', '7.4', '161213'], ['Zootopia', '1023784195', '8.1', '302479'], ['The Jungle Book', '966550600', '7.5', '200798'], ['The Secret Life Of Pets', '875457937', '6.6', '124027'], ['Batman v Superman', '873260194', '6.7', '479880'], ['Deadpool', '783112979', '8.0', '637685'], ['Suicide Squad', '745600054', '6.2', '404862'], ['Sing', '632443719', '7.2', '66129']]\n"
- ]
- }
- ],
- "source": [
- "with open('topmovies.csv', encoding='UTF-8') as f:\n",
- " moviescsv = csv.reader(f, delimiter=',', skipinitialspace=True)\n",
- "\n",
- " movielist = [line for line in moviescsv]\n",
- "\n",
- "print(movielist)\n",
- " "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This is, of course, a rather crude demonstration (in fact it breaks our rule of avoiding lists of mixed types); we'd likely want to be more organized with how we structure the data we obtain from a csv, but that will depend on your individual needs.\n",
- "\n",
- "Writing to a csv is basically just as easy, and follows practically the same format. Let's put the movielist into a new csv, with different delimiters, and quotation marks around non-numeric data (this will make it easier to import in the future, since with this style, the reader can distinguish between numbers and strings when it reads the file. Firstly, we should actually convert the numeric data into numbers:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[['movie name', 'gross', 'IMDB rating', 'IMDB votes'], ['Captain America: Civil War', 1153304495.0, 7.9, 418614.0], ['Rogue One', 1056057273.0, 7.9, 334132.0], ['Finding Dory', 1028570889.0, 7.4, 161213.0], ['Zootopia', 1023784195.0, 8.1, 302479.0], ['The Jungle Book', 966550600.0, 7.5, 200798.0], ['The Secret Life Of Pets', 875457937.0, 6.6, 124027.0], ['Batman v Superman', 873260194.0, 6.7, 479880.0], ['Deadpool', 783112979.0, 8.0, 637685.0], ['Suicide Squad', 745600054.0, 6.2, 404862.0], ['Sing', 632443719.0, 7.2, 66129.0]]\n"
- ]
- }
- ],
- "source": [
- "for row in movielist:\n",
- " for i, entry in enumerate(row):\n",
- " try:\n",
- " row[i] = float(entry)\n",
- " except ValueError:\n",
- " pass\n",
- "\n",
- "print(movielist)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Exactly how this code works will be explained in a future article, but try and guess what it does anyway! (Clue: float(\"movie name\") will usually produce an error. What do try and except do?) "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now that our table is in a nicer format, let's write it to a csv."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "with open(\"movies-new.csv\", \"w\", encoding='UTF-8') as f:\n",
- " # creates a \"writer\" that is ready to write whatever we give to it\n",
- " moviecsv = csv.writer(f, delimiter='|', quotechar=\"`\", quoting=csv.QUOTE_NONNUMERIC)\n",
- " \n",
- " # give the list to the writer\n",
- " moviecsv.writerows(movielist)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The resulting file on my computer looks like this:"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "`movie name`|`gross`|`IMDB rating`|`IMDB votes`\n",
- "`Captain America: Civil War`|1153304495.0|7.9|418614.0\n",
- "`Rogue One`|1056057273.0|7.9|334132.0\n",
- "`Finding Dory`|1028570889.0|7.4|161213.0\n",
- "`Zootopia`|1023784195.0|8.1|302479.0\n",
- "`The Jungle Book`|966550600.0|7.5|200798.0\n",
- "`The Secret Life Of Pets`|875457937.0|6.6|124027.0\n",
- "`Batman v Superman`|873260194.0|6.7|479880.0\n",
- "`Deadpool`|783112979.0|8.0|637685.0\n",
- "`Suicide Squad`|745600054.0|6.2|404862.0\n",
- "`Sing`|632443719.0|7.2|66129.0"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Each argument here should be fairly self-explanatory. Rows can be written one at a time with writer.writerow(row), instead of providing a full list all at once."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## JSON\n",
- "\n",
- "JSON stands for \"JavaScript Object Notation\". JavaScript is a programming languaged used to make interactive and dynamic webpages. This means there needs to be a way for a JavaScript script in a webpage to send and receive bundles of data without reloading the whole page. The JSON file format is one such solution. However, JSON files can be used to store many kinds of data, and are commonly encountered when grabbing information from the web. In fact, Jupyter notebook files such as this very article are really just JSON files with a different suffix; try opening one in your text editor to see for yourself!\n",
- "\n",
- "Thankfully for us, JSON files are easy for any Python programmer to understand. Here is an example of a JSON file containing an Amazon review for a piece of audio equipment (and yes, Amazon reviews really are sent over to your computer as JSON - in fact most of the things you see on any given Amazon page are):"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "{\"reviewerID\": \"A2C00NNG1ZQQG2\",\n",
- "\"asin\": \"1384719342\",\n",
- "\"reviewerName\": \"RustyBill \\\"Sunday Rocker\\\"\",\n",
- "\"helpful\": [0, 0],\n",
- "\"reviewText\": \"Nice windscreen protects my MXL mic and prevents pops. Only thing is that the gooseneck is only marginally able to hold the screen in position and requires careful positioning of the clamp to avoid sagging.\",\n",
- "\"overall\": 5.0,\n",
- "\"summary\": \"GOOD WINDSCREEN FOR THE MONEY\",\n",
- "\"unixReviewTime\": 1392336000,\n",
- "\"reviewTime\": \"02 14, 2014\"}"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Look familiar? It's basically just a dictionary. This is a good reason for Python programmers to know about JSON files, as it means we can save the data in our Python programs on an external file, so long as the values are of a suitable format (strings, numbers, etc)."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Of course, it's not precisely a dictionary. There are some translations that need to be made from the JSON format (and terminology). The dictionary-like structure of a JSON file is called a JSON object. Since objects can have objects as their values, this gives JSON objects a tree-like structure. Booleans in JSON files use all lower case (so Python's True is true in JSON). Lists and tuples are rolled into one object called an array, and all floats and ints are rolled into one object called a number. Let's see how we can import JSONs, using the json module, which does all the necessary translations for us (phew!)."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The main functions of the module are dump and dumps (for creating JSON objects), and load and loads (for reading JSON objects). The s appearing in two of these functions simply stands for string. We'll see the difference in a second."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "{'reviewerID': 'A2IBPI20UZIR0U', 'asin': '1384719342', 'reviewerName': 'cassandra tu \"Yeah, well, that\\'s just like, u...', 'helpful': [0, 0], 'reviewText': \"Not much to write about here, but it does exactly what it's supposed to. filters out the pop sounds. now my recordings are much more crisp. it is one of the lowest prices pop filters on amazon so might as well buy it, they honestly work the same despite their pricing,\", 'overall': 5.0, 'summary': 'good', 'unixReviewTime': 1393545600, 'reviewTime': '02 28, 2014'}\n",
- "{'reviewerID': 'A14VAT5EAX3D9S', 'asin': '1384719342', 'reviewerName': 'Jake', 'helpful': [13, 14], 'reviewText': \"The product does exactly as it should and is quite affordable.I did not realized it was double screened until it arrived, so it was even better than I had expected.As an added bonus, one of the screens carries a small hint of the smell of an old grape candy I used to buy, so for reminiscent's sake, I cannot stop putting the pop filter next to my nose and smelling it after recording. :DIf you needed a pop filter, this will work just as well as the expensive ones, and it may even come with a pleasing aroma like mine did!Buy this product! :]\", 'overall': 5.0, 'summary': 'Jake', 'unixReviewTime': 1363392000, 'reviewTime': '03 16, 2013'}\n",
- "{'reviewerID': 'A195EZSQDW3E21', 'asin': '1384719342', 'reviewerName': 'Rick Bennette \"Rick Bennette\"', 'helpful': [1, 1], 'reviewText': 'The primary job of this device is to block the breath that would otherwise produce a popping sound, while allowing your voice to pass through with no noticeable reduction of volume or high frequencies. The double cloth filter blocks the pops and lets the voice through with no coloration. The metal clamp mount attaches to the mike stand secure enough to keep it attached. The goose neck needs a little coaxing to stay where you put it.', 'overall': 5.0, 'summary': 'It Does The Job Well', 'unixReviewTime': 1377648000, 'reviewTime': '08 28, 2013'}\n",
- "{'reviewerID': 'A2C00NNG1ZQQG2', 'asin': '1384719342', 'reviewerName': 'RustyBill \"Sunday Rocker\"', 'helpful': [0, 0], 'reviewText': 'Nice windscreen protects my MXL mic and prevents pops. Only thing is that the gooseneck is only marginally able to hold the screen in position and requires careful positioning of the clamp to avoid sagging.', 'overall': 5.0, 'summary': 'GOOD WINDSCREEN FOR THE MONEY', 'unixReviewTime': 1392336000, 'reviewTime': '02 14, 2014'}\n",
- "{'reviewerID': 'A94QU4C90B1AX', 'asin': '1384719342', 'reviewerName': 'SEAN MASLANKA', 'helpful': [0, 0], 'reviewText': \"This pop filter is great. It looks and performs like a studio filter. If you're recording vocals this will eliminate the pops that gets recorded when you sing.\", 'overall': 5.0, 'summary': 'No more pops when I record my vocals.', 'unixReviewTime': 1392940800, 'reviewTime': '02 21, 2014'}\n"
- ]
- }
- ],
- "source": [
- "import json\n",
- "with open(\"Musical_Instruments_5.json\", \"r\", encoding='UTF-8') as f:\n",
- " reviews = [json.loads(line) for line in f]\n",
- "\n",
- "for review in reviews[:5]:\n",
- " print(review)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Let's break it down. As usual, we open the file using open to give us a file object. This file contains a different JSON object on each line. Because we can read through a file line-by-line, and those lines are read as text, we use loads because each line is a string.\n",
- "\n",
- "One we have loaded it, each JSON object is now precisely a dictionary:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "This person thought the product they purchased was: good\n"
- ]
- }
- ],
- "source": [
- "print(type(reviews[0]))\n",
- "print(\"This person thought the product they purchased was: {}\".format(reviews[0][\"summary\"]))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This strategy is very good when we have a file containing lots of JSON objects. We read each object (line) as a string and then pass it to loads to convert it. If we have a file containing only a single JSON object, we can pass the whole file to load instead:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Spiritually and mentally inspiring! A book that allows you to question your morals and will help you discover who you really are!\n"
- ]
- }
- ],
- "source": [
- "with open(\"book_review.json\", encoding='UTF-8') as f:\n",
- " bookreview = json.load(f)\n",
- "\n",
- "print(bookreview[\"reviewText\"])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Writing JSON objects to files is much the same scenario. This provides a convenient way to save the important information in a Python program, in a way that can be re-opened by the same program, another Python program, or even a program written in a different programming language.\n",
- "\n",
- "Let's encode a JSON object. Suppose I run a business and my program is storing the delivery details of my customers. I might store each customer as a dictionary like this:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "customer = {\n",
- " 'name': 'Sam Cassidy',\n",
- " 'address': '19 Notareal Avenue, Liverpool',\n",
- " 'postcode': 'L00 9JR',\n",
- " 'purchase-history': [('inflatable pet', 3, '05.09.2016'),\n",
- " ('disposable widget', 60, '01.01.2017')],\n",
- " 'Phone number': '0712345567889'\n",
- "}"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "So the information contained here is mostly strings, although some are organized into lists of tuples, and there's also a couple of integers here as well. Let's create a JSON object from this dictionary."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "customer_JSON = json.dumps(customer)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "{\"name\": \"Sam Cassidy\", \"address\": \"19 Notareal Avenue, Liverpool\", \"postcode\": \"L00 9JR\", \"purchase-history\": [[\"inflatable pet\", 3, \"05.09.2016\"], [\"disposable widget\", 60, \"01.01.2017\"]]}\n"
- ]
- }
- ],
- "source": [
- "print(customer_JSON)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "As we can see, the reproduction is mostly faithful, but our tuples have been turned into JSON arrays. That's okay: if we wish to recover the original tuples when we load from this JSON file, we can just write a function to convert them back.\n",
- "\n",
- "JSON files ignore whitespace, so we can actually make a slightly nicer JSON file by setting the indent parameter:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "{\n",
- " \"name\": \"Sam Cassidy\",\n",
- " \"address\": \"19 Notareal Avenue, Liverpool\",\n",
- " \"postcode\": \"L00 9JR\",\n",
- " \"purchase-history\": [\n",
- " [\n",
- " \"inflatable pet\",\n",
- " 3,\n",
- " \"05.09.2016\"\n",
- " ],\n",
- " [\n",
- " \"disposable widget\",\n",
- " 60,\n",
- " \"01.01.2017\"\n",
- " ]\n",
- " ]\n",
- "}\n"
- ]
- }
- ],
- "source": [
- "customer_JSON = json.dumps(customer, indent=2)\n",
- "print(customer_JSON)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Which is easier to read, and closer to how we defined customer in the file. Since this is now just a string, we can write it to a .json file using the usual write methods:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "with open('my_customers.json', 'a', encoding='UTF-8') as f:\n",
- " f.write(customer_JSON)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "And there, the data is saved and can be reopened using json.load() or json.loads().\n",
- "\n",
- "The difficulty with JSON files is that ultimately, they're only text files. For one, this means encoding is sometimes important, and all the previous things we've said about encoding should be considered. For two, this means that more complicated Python data structures (for example custom made classes, which we'll meet soon enough) might need to be cleverly converted into text, somehow or other. For instance, it might be more useful to inside my program to work with Python's smart \"date\" objects, rather than just strings containing the date:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [],
- "source": [
- "from datetime import date\n",
- "customer = {\n",
- " 'name': 'Sam Cassidy',\n",
- " 'address': '19 Notareal Avenue, Liverpool',\n",
- " 'postcode': 'L00 9JR',\n",
- " 'purchase-history': [('inflatable pet', 3, date(2016, 9, 5)),\n",
- " ('disposable widget', 60, date(2017, 1, 1))],\n",
- " 'Phone number': '0712345567889'\n",
- "}"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The date object is much smarter than a string. For example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 21,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "2016-09-05\n",
- "1\n",
- "Monday 05 September\n"
- ]
- }
- ],
- "source": [
- "inflatable_pet_date = customer['purchase-history'][0][2]\n",
- "print(inflatable_pet_date)\n",
- "print(inflatable_pet_date.isoweekday()) # day of the week as a number-- this day was a Monday (1st day)!\n",
- "print(inflatable_pet_date.strftime('%A %d %B')) # there's a little mini language to control\n",
- " # this representatio"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now let's write this object to a JSON again:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 23,
- "metadata": {},
- "outputs": [
- {
- "ename": "TypeError",
- "evalue": "Object of type 'date' is not JSON serializable",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mcustomer_JSON\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mjson\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdumps\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcustomer\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mindent\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;32m/home/sam/anaconda3/lib/python3.6/json/__init__.py\u001b[0m in \u001b[0;36mdumps\u001b[0;34m(obj, skipkeys, ensure_ascii, check_circular, allow_nan, cls, indent, separators, default, sort_keys, **kw)\u001b[0m\n\u001b[1;32m 236\u001b[0m \u001b[0mcheck_circular\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mcheck_circular\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mallow_nan\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mallow_nan\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mindent\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mindent\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 237\u001b[0m \u001b[0mseparators\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mseparators\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdefault\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdefault\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msort_keys\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0msort_keys\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 238\u001b[0;31m **kw).encode(obj)\n\u001b[0m\u001b[1;32m 239\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 240\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;32m/home/sam/anaconda3/lib/python3.6/json/encoder.py\u001b[0m in \u001b[0;36mencode\u001b[0;34m(self, o)\u001b[0m\n\u001b[1;32m 199\u001b[0m \u001b[0mchunks\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0miterencode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mo\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_one_shot\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 200\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mchunks\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mlist\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 201\u001b[0;31m \u001b[0mchunks\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mchunks\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 202\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mchunks\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 203\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;32m/home/sam/anaconda3/lib/python3.6/json/encoder.py\u001b[0m in \u001b[0;36m_iterencode\u001b[0;34m(o, _current_indent_level)\u001b[0m\n\u001b[1;32m 428\u001b[0m \u001b[0;32myield\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0m_iterencode_list\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mo\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_current_indent_level\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 429\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mo\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdict\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 430\u001b[0;31m \u001b[0;32myield\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0m_iterencode_dict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mo\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_current_indent_level\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 431\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 432\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mmarkers\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;32m/home/sam/anaconda3/lib/python3.6/json/encoder.py\u001b[0m in \u001b[0;36m_iterencode_dict\u001b[0;34m(dct, _current_indent_level)\u001b[0m\n\u001b[1;32m 402\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 403\u001b[0m \u001b[0mchunks\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_iterencode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_current_indent_level\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 404\u001b[0;31m \u001b[0;32myield\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mchunks\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 405\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mnewline_indent\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 406\u001b[0m \u001b[0m_current_indent_level\u001b[0m \u001b[0;34m-=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;32m/home/sam/anaconda3/lib/python3.6/json/encoder.py\u001b[0m in \u001b[0;36m_iterencode_list\u001b[0;34m(lst, _current_indent_level)\u001b[0m\n\u001b[1;32m 323\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 324\u001b[0m \u001b[0mchunks\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_iterencode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_current_indent_level\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 325\u001b[0;31m \u001b[0;32myield\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mchunks\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 326\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mnewline_indent\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 327\u001b[0m \u001b[0m_current_indent_level\u001b[0m \u001b[0;34m-=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;32m/home/sam/anaconda3/lib/python3.6/json/encoder.py\u001b[0m in \u001b[0;36m_iterencode_list\u001b[0;34m(lst, _current_indent_level)\u001b[0m\n\u001b[1;32m 323\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 324\u001b[0m \u001b[0mchunks\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_iterencode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_current_indent_level\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 325\u001b[0;31m \u001b[0;32myield\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mchunks\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 326\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mnewline_indent\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 327\u001b[0m \u001b[0m_current_indent_level\u001b[0m \u001b[0;34m-=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;32m/home/sam/anaconda3/lib/python3.6/json/encoder.py\u001b[0m in \u001b[0;36m_iterencode\u001b[0;34m(o, _current_indent_level)\u001b[0m\n\u001b[1;32m 435\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Circular reference detected\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 436\u001b[0m \u001b[0mmarkers\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mmarkerid\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mo\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 437\u001b[0;31m \u001b[0mo\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_default\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mo\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 438\u001b[0m \u001b[0;32myield\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0m_iterencode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mo\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_current_indent_level\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 439\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mmarkers\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;32m/home/sam/anaconda3/lib/python3.6/json/encoder.py\u001b[0m in \u001b[0;36mdefault\u001b[0;34m(self, o)\u001b[0m\n\u001b[1;32m 178\u001b[0m \"\"\"\n\u001b[1;32m 179\u001b[0m raise TypeError(\"Object of type '%s' is not JSON serializable\" %\n\u001b[0;32m--> 180\u001b[0;31m o.__class__.__name__)\n\u001b[0m\u001b[1;32m 181\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 182\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mencode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mo\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;31mTypeError\u001b[0m: Object of type 'date' is not JSON serializable"
- ]
- }
- ],
- "source": [
- "customer_JSON = json.dumps(customer, indent=2)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Umm... ouch. A simple solution is to write functions that can convert to and from strings and date objects, and just apply them before and after encoding or decoding. The date module of course already provides a way to convert the date to a string -- you can just use str() on the object."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 29,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "def customer_to_jsonable(customer):\n",
- " from copy import copy\n",
- " # so we don't damage the original dictionary\n",
- " customer = copy(customer)\n",
- " for i, entry in enumerate(customer['purchase-history']):\n",
- " customer['purchase-history'][i] = (entry[0], entry[1], str(entry[2]))\n",
- " return customer\n",
- "\n",
- "def json_to_customer(jsonCust):\n",
- " for i, entry in enumerate(jsonCust['purchase-history']):\n",
- " date_list = entry[2].split('-')\n",
- " date_list = [int(x) for x in date_list]\n",
- " jsonCust['purchase-history'][i] = (entry[0], entry[1], date(date_list[0], date_list[1], date_list[2]))\n",
- " return jsonCust\n",
- " "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 30,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "# now call the function before converting to JSON\n",
- "customer_JSON = json.dumps(customer_to_jsonable(customer), indent=2)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 31,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "{\n",
- " \"name\": \"Sam Cassidy\",\n",
- " \"address\": \"19 Notareal Avenue, Liverpool\",\n",
- " \"postcode\": \"L00 9JR\",\n",
- " \"purchase-history\": [\n",
- " [\n",
- " \"inflatable pet\",\n",
- " 3,\n",
- " \"2016-09-05\"\n",
- " ],\n",
- " [\n",
- " \"disposable widget\",\n",
- " 60,\n",
- " \"2017-01-01\"\n",
- " ]\n",
- " ],\n",
- " \"Phone number\": \"0712345567889\"\n",
- "}\n"
- ]
- }
- ],
- "source": [
- "print(customer_JSON)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 39,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "{'name': 'Sam Cassidy', 'address': '19 Notareal Avenue, Liverpool', 'postcode': 'L00 9JR', 'purchase-history': [('inflatable pet', 3, datetime.date(2016, 9, 5)), ('disposable widget', 60, datetime.date(2017, 1, 1))], 'Phone number': '0712345567889'} \n",
- "\n",
- "Customer Sam Cassidy purchased inflatable pet on:\n",
- "2016-09-05\n"
- ]
- }
- ],
- "source": [
- "original_customer = json_to_customer(json.loads(customer_JSON))\n",
- "print(original_customer, '\\n')\n",
- "print(\"Customer {} purchased {} on:\".format(original_customer['name'],\n",
- " original_customer['purchase-history'][0][0]))\n",
- "print(original_customer['purchase-history'][0][2])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "So, with a little bit of thinking and tinkering, we've recovered all of the original information, even though JSON only allows us to store text.\n",
- "\n",
- "## XML\n",
- "\n",
- "There's another very common way to store and manipulate data on the web. It's called XML, and is in many ways like JSON, but more flexible, and more complicated. Python has an xml module for working with these formats, which again converts hierarchies of attributes into dictionary. There's a great article about how the format works and how to use xml here: http://www.diveintopython3.net/xml.html."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.1"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 1
-}
diff --git a/PurePy 7. Importing Data/.ipynb_checkpoints/Reading and storing data; CSV, JSON, and XML-checkpoint.ipynb b/PurePy 7. Importing Data/.ipynb_checkpoints/Reading and storing data; CSV, JSON, and XML-checkpoint.ipynb
deleted file mode 100644
index 8cf85c3..0000000
--- a/PurePy 7. Importing Data/.ipynb_checkpoints/Reading and storing data; CSV, JSON, and XML-checkpoint.ipynb
+++ /dev/null
@@ -1,417 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "There is a natural dichotomy between data files that are easy for a computer to read, and data files that are easy for a human to read. In this article, we'll look at three common kinds of data files you are likely to encounter, are fairly human-readable, as well as being very easily manipulated in Python.\n",
- "\n",
- "## CSV files\n",
- "\n",
- "CSV is a very simple file format. The initials stand for \"comma-separated values\", and is used to encode a table of data. All spreadsheets and most databases can be exported into CSV format, and spreadsheet software such as Excel can import CSV files, so this is a nice format to be familiar with. Line-breaks (that is, \\n or \\r characters) separate the rows, and commas separate the values in each row. Well, it's a bit more lenient than that; you can choose any character to separate the values, but comma is the one that stuck around in the name for some reason. So, this is a perfectly reasonable .csv file:"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "item,price\n",
- "bread,1.50\n",
- "rice,3.00\n",
- "bananas,0.30\n",
- "applesauce,2.00"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "but so is"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "item|price\n",
- "bread|1.50\n",
- "rice|3.00\n",
- "bananas|0.30\n",
- "applesauce|2.00"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "As we should have come to expect in Python, there is a standard library module for handling .csv files, called (wait for it) csv. The two main functions offered by this module are reader() and writer(), respectively used for reading and writing csv files. Let's look at reading, first."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Pretty printing has been turned ON\n",
- "['movie name', ' gross', 'IMDB rating', 'IMDB votes']\n",
- "['Captain America: Civil War', ' 1153304495', '7.9', '418614']\n",
- "['Rogue One', ' 1056057273', '7.9', '334132']\n",
- "['Finding Dory', ' 1028570889', '7.4', '161213']\n",
- "['Zootopia', ' 1023784195', '8.1', '302479']\n",
- "['The Jungle Book', ' 966550600', '7.5', '200798']\n",
- "['The Secret Life Of Pets', ' 875457937', '6.6', '124027']\n",
- "['Batman v Superman', ' 873260194', '6.7', '479880']\n",
- "['Deadpool', ' 783112979', '8.0', '637685']\n",
- "['Suicide Squad', ' 745600054', '6.2', '404862']\n",
- "['Sing', ' 632443719', '7.2', '66129']\n"
- ]
- }
- ],
- "source": [
- "import csv\n",
- "with open('topmovies.csv', newline='') as f: # file contains highest grossing films of 2016\n",
- " moviescsv = csv.reader(f, delimiter=',')\n",
- "\n",
- " for line in moviescsv:\n",
- " print(line)\n",
- " "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "As we can see, each line is turned into a list of strings (by default). In this use of reader, we specified a delimiter character -- the character that separates each entry. We chose a comma, although this is redundant since it is the default anyway.\n",
- "\n",
- "We can see a problem with this import. Most entries have a space following the comma, which we don't want. This is easily fixed:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "['movie name', 'gross', 'IMDB rating', 'IMDB votes']\n",
- "['Captain America: Civil War', '1153304495', '7.9', '418614']\n",
- "['Rogue One', '1056057273', '7.9', '334132']\n",
- "['Finding Dory', '1028570889', '7.4', '161213']\n",
- "['Zootopia', '1023784195', '8.1', '302479']\n",
- "['The Jungle Book', '966550600', '7.5', '200798']\n",
- "['The Secret Life Of Pets', '875457937', '6.6', '124027']\n",
- "['Batman v Superman', '873260194', '6.7', '479880']\n",
- "['Deadpool', '783112979', '8.0', '637685']\n",
- "['Suicide Squad', '745600054', '6.2', '404862']\n",
- "['Sing', '632443719', '7.2', '66129']\n"
- ]
- }
- ],
- "source": [
- "with open('topmovies.csv', newline='') as f:\n",
- " moviescsv = csv.reader(f, delimiter=',', skipinitialspace=True)\n",
- "\n",
- " for line in moviescsv:\n",
- " print(line)\n",
- " "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The csv.reader object provides a large number of options and fixes to get the import just right. Another consideration with csvs is \"what if the entry contains the delimiter?\" For example, what if one of the movie titles in the file I imported contained a comma? For this, we use quotes: punctuation inside quotation marks is ignored. Hence, the csv reader also allows us to specify which character is used for quoting.\n",
- "\n",
- "The csv.reader object has not created a copy of the csv file in Python's memory; it is still reading from the file. Therefore, the file must still be open when we access the lines via the reader. If we want to close the file, we should move the entries into another structure such as a list or dictionary:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[['movie name', 'gross', 'IMDB rating', 'IMDB votes'], ['Captain America: Civil War', '1153304495', '7.9', '418614'], ['Rogue One', '1056057273', '7.9', '334132'], ['Finding Dory', '1028570889', '7.4', '161213'], ['Zootopia', '1023784195', '8.1', '302479'], ['The Jungle Book', '966550600', '7.5', '200798'], ['The Secret Life Of Pets', '875457937', '6.6', '124027'], ['Batman v Superman', '873260194', '6.7', '479880'], ['Deadpool', '783112979', '8.0', '637685'], ['Suicide Squad', '745600054', '6.2', '404862'], ['Sing', '632443719', '7.2', '66129']]\n"
- ]
- }
- ],
- "source": [
- "with open('topmovies.csv', newline='') as f:\n",
- " moviescsv = csv.reader(f, delimiter=',', skipinitialspace=True)\n",
- "\n",
- " movielist = [line for line in moviescsv]\n",
- "\n",
- "print(movielist)\n",
- " "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This is, of course, a rather crude demonstration (in fact it breaks our rule of avoiding lists of mixed types); we'd likely want to be more organized with how we structure the data we obtain from a csv, but that will depend on your individual needs.\n",
- "\n",
- "Writing to a csv is basically just as easy, and follows practically the same format. Let's put the movielist into a new csv, with different delimiters, and quotation marks around non-numeric data (this will make it easier to import in the future, since with this style, the reader can distinguish between numbers and strings when it reads the file. Firstly, we should actually convert the numeric data into numbers:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[['movie name', 'gross', 'IMDB rating', 'IMDB votes'], ['Captain America: Civil War', 1153304495.0, 7.9, 418614.0], ['Rogue One', 1056057273.0, 7.9, 334132.0], ['Finding Dory', 1028570889.0, 7.4, 161213.0], ['Zootopia', 1023784195.0, 8.1, 302479.0], ['The Jungle Book', 966550600.0, 7.5, 200798.0], ['The Secret Life Of Pets', 875457937.0, 6.6, 124027.0], ['Batman v Superman', 873260194.0, 6.7, 479880.0], ['Deadpool', 783112979.0, 8.0, 637685.0], ['Suicide Squad', 745600054.0, 6.2, 404862.0], ['Sing', 632443719.0, 7.2, 66129.0]]\n"
- ]
- }
- ],
- "source": [
- "for row in movielist:\n",
- " for i, entry in enumerate(row):\n",
- " try:\n",
- " row[i] = float(entry)\n",
- " except ValueError:\n",
- " pass\n",
- "\n",
- "print(movielist)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Exactly how this code works will be explained in a future article, but try and guess what it does anyway! (Clue: float(\"movie name\") will usually produce an error. What do try and except do?) "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now that our table is in a nicer format, let's write it to a csv."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "with open(\"movies-new.csv\", \"w\", newline='') as f:\n",
- " # creates a \"writer\" that is ready to write whatever we give to it\n",
- " moviecsv = csv.writer(f, delimiter='|', quotechar=\"`\", quoting=csv.QUOTE_NONNUMERIC)\n",
- " \n",
- " # give the list to the writer\n",
- " moviecsv.writerows(movielist)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The resulting file on my computer looks like this:"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "`movie name`|`gross`|`IMDB rating`|`IMDB votes`\n",
- "`Captain America: Civil War`|1153304495.0|7.9|418614.0\n",
- "`Rogue One`|1056057273.0|7.9|334132.0\n",
- "`Finding Dory`|1028570889.0|7.4|161213.0\n",
- "`Zootopia`|1023784195.0|8.1|302479.0\n",
- "`The Jungle Book`|966550600.0|7.5|200798.0\n",
- "`The Secret Life Of Pets`|875457937.0|6.6|124027.0\n",
- "`Batman v Superman`|873260194.0|6.7|479880.0\n",
- "`Deadpool`|783112979.0|8.0|637685.0\n",
- "`Suicide Squad`|745600054.0|6.2|404862.0\n",
- "`Sing`|632443719.0|7.2|66129.0"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Each argument here should be fairly self-explanatory. Rows can be written one at a time with writer.writerow(row), instead of providing a full list all at once."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## JSON\n",
- "\n",
- "JSON stands for \"JavaScript Object Notation\". JavaScript is a programming languaged used to make interactive and dynamic webpages. This means there needs to be a way for a JavaScript script in a webpage to send and receive bundles of data without reloading the whole page. The JSON file format is one such solution. However, JSON files can be used to store many kinds of data, and are commonly encountered when grabbing information from the web. In fact, Jupyter notebook files such as this very article are really just JSON files with a different suffix; try opening one in your text editor to see for yourself!\n",
- "\n",
- "Thankfully for us, JSON files are easy for any Python programmer to understand. Here is an example of a JSON file containing an Amazon review for a piece of audio equipment (and yes, Amazon reviews really are sent over to your computer as JSON - in fact most of the things you see on any given Amazon page are):"
- ]
- },
- {
- "cell_type": "raw",
- "metadata": {},
- "source": [
- "{\"reviewerID\": \"A2C00NNG1ZQQG2\",\n",
- "\"asin\": \"1384719342\",\n",
- "\"reviewerName\": \"RustyBill \\\"Sunday Rocker\\\"\",\n",
- "\"helpful\": [0, 0],\n",
- "\"reviewText\": \"Nice windscreen protects my MXL mic and prevents pops. Only thing is that the gooseneck is only marginally able to hold the screen in position and requires careful positioning of the clamp to avoid sagging.\",\n",
- "\"overall\": 5.0,\n",
- "\"summary\": \"GOOD WINDSCREEN FOR THE MONEY\",\n",
- "\"unixReviewTime\": 1392336000,\n",
- "\"reviewTime\": \"02 14, 2014\"}"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Look familiar? It's basically just a dictionary. This is a good reason for Python programmers to know about JSON files, as it means we can save the data in our dictionaries on an external file, so long as the values are of a suitable format (strings, numbers, etc)."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Of course, it's not precisely a dictionary. There are some translations that need to be made from the JSON format (and terminology). The dictionary-like structure of a JSON file is called a JSON object. Since objects can have objects as their values, this gives JSON objects a tree-like structure. Booleans in JSON files use all lower case (so Python's True is true in JSON). Lists and tuples are rolled into one object called an array, and all floats and ints are rolled into one object called a number. Let's see how we can import JSONs, using the json module, which does all the necessary translations for us (phew!)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The main functions of the module are dump and dumps (for creating JSON objects), and load and loads (for reading JSON objects). The s appearing in two of these functions simply stands for string. We'll see the difference in a second."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "{'reviewTime': '02 28, 2014', 'reviewerID': 'A2IBPI20UZIR0U', 'reviewerName': 'cassandra tu \"Yeah, well, that\\'s just like, u...', 'overall': 5.0, 'summary': 'good', 'asin': '1384719342', 'helpful': [0, 0], 'reviewText': \"Not much to write about here, but it does exactly what it's supposed to. filters out the pop sounds. now my recordings are much more crisp. it is one of the lowest prices pop filters on amazon so might as well buy it, they honestly work the same despite their pricing,\", 'unixReviewTime': 1393545600}\n",
- "{'reviewTime': '03 16, 2013', 'reviewerID': 'A14VAT5EAX3D9S', 'reviewerName': 'Jake', 'overall': 5.0, 'summary': 'Jake', 'asin': '1384719342', 'helpful': [13, 14], 'reviewText': \"The product does exactly as it should and is quite affordable.I did not realized it was double screened until it arrived, so it was even better than I had expected.As an added bonus, one of the screens carries a small hint of the smell of an old grape candy I used to buy, so for reminiscent's sake, I cannot stop putting the pop filter next to my nose and smelling it after recording. :DIf you needed a pop filter, this will work just as well as the expensive ones, and it may even come with a pleasing aroma like mine did!Buy this product! :]\", 'unixReviewTime': 1363392000}\n",
- "{'reviewTime': '08 28, 2013', 'reviewerID': 'A195EZSQDW3E21', 'reviewerName': 'Rick Bennette \"Rick Bennette\"', 'overall': 5.0, 'summary': 'It Does The Job Well', 'asin': '1384719342', 'helpful': [1, 1], 'reviewText': 'The primary job of this device is to block the breath that would otherwise produce a popping sound, while allowing your voice to pass through with no noticeable reduction of volume or high frequencies. The double cloth filter blocks the pops and lets the voice through with no coloration. The metal clamp mount attaches to the mike stand secure enough to keep it attached. The goose neck needs a little coaxing to stay where you put it.', 'unixReviewTime': 1377648000}\n",
- "{'reviewTime': '02 14, 2014', 'reviewerID': 'A2C00NNG1ZQQG2', 'reviewerName': 'RustyBill \"Sunday Rocker\"', 'overall': 5.0, 'summary': 'GOOD WINDSCREEN FOR THE MONEY', 'asin': '1384719342', 'helpful': [0, 0], 'reviewText': 'Nice windscreen protects my MXL mic and prevents pops. Only thing is that the gooseneck is only marginally able to hold the screen in position and requires careful positioning of the clamp to avoid sagging.', 'unixReviewTime': 1392336000}\n",
- "{'reviewTime': '02 21, 2014', 'reviewerID': 'A94QU4C90B1AX', 'reviewerName': 'SEAN MASLANKA', 'overall': 5.0, 'summary': 'No more pops when I record my vocals.', 'asin': '1384719342', 'helpful': [0, 0], 'reviewText': \"This pop filter is great. It looks and performs like a studio filter. If you're recording vocals this will eliminate the pops that gets recorded when you sing.\", 'unixReviewTime': 1392940800}\n"
- ]
- }
- ],
- "source": [
- "import json\n",
- "with open(\"Musical_Instruments_5.json\", \"r\") as f:\n",
- " reviews = [json.loads(line) for line in f]\n",
- "\n",
- "for review in reviews[:5]:\n",
- " print(review)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Let's break it down. As usual, we open the file using open to give us a file object. This file contains a different JSON object on each line. Because we can read through a file line-by-line, and those lines are read as text, we use loads because each line is a string.\n",
- "\n",
- "One we have loaded it, each JSON object is now precisely a dictionary:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 17,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "This person thought the product they purchased was: good\n"
- ]
- }
- ],
- "source": [
- "print(type(reviews[0]))\n",
- "print(\"This person thought the product they purchased was: {}\".format(reviews[0][\"summary\"]))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This strategy is very good when we have a file containing lots of JSON objects. We read each object (line) as a string and then pass it to loads to convert it. If we have a file containing only a single JSON object, we can pass the whole file to load instead:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Spiritually and mentally inspiring! A book that allows you to question your morals and will help you discover who you really are!\n"
- ]
- }
- ],
- "source": [
- "with open(\"book_review.json\") as f:\n",
- " bookreview = json.load(f)\n",
- "\n",
- "print(bookreview[\"reviewText\"])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Writing JSON objects to files is much the same scenario."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.5.2"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 1
-}
diff --git a/PurePy 8. Advanced Flow Control/.ipynb_checkpoints/8.0 Advanced Flow Control-checkpoint.ipynb b/PurePy 8. Advanced Flow Control/.ipynb_checkpoints/8.0 Advanced Flow Control-checkpoint.ipynb
deleted file mode 100644
index 9b6c130..0000000
--- a/PurePy 8. Advanced Flow Control/.ipynb_checkpoints/8.0 Advanced Flow Control-checkpoint.ipynb
+++ /dev/null
@@ -1,726 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# More Flow Control\n",
- "\n",
- "So far, we have met if, elif and else, as well as for-loops and while-loops. Now we take a look at some more tools we have to control the behaviour of loops. Briefly before that though."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## The pass statement"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The statement pass is simply the \"do nothing\" statement. Including this somewhere in your code does precisely nothing. However, it is formally a valid Python statement. Therefore it can be used as a placeholder in a location where Python formally requires some code, but you either don't want to do anything, or simply haven't got round to it. For example, when you start designing a sequence of ifs and elifs, you may want to write out each possible choice ahead of writing out what to do in each case. Hence, we might write the Fizzbuzz challenge first like this:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "for x in range(100):\n",
- " if x % 3 == 0 and x % 5 == 0:\n",
- " pass\n",
- " elif x % 3 == 0:\n",
- " pass\n",
- " elif x % 5 == 0:\n",
- " pass\n",
- " else:\n",
- " pass"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This way, we can see some of the structure of the program, even we've not filled in the details yet. This is particularly useful when you are breaking your problem down into different functions; you can easily see what is yet to be done, especially when combined with doc strings."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "## example here"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## More logical checking tools\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Using other types as stand-ins for Booleans\n",
- "\n",
- "A neat thing about Python is that if we use a non-Boolean type in a logical expression, Python will have a go at interpreting it as a Boolean anyway.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "0\n"
- ]
- }
- ],
- "source": [
- "print(1 and 0)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "1\n"
- ]
- }
- ],
- "source": [
- "print(1 and 1)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "In this case, Python knows to use 0 as False, and 1 as True. This works for all kinds of things, but the rule of thumb is this. If you give Python numbers in a boolean expression, 0 is considered False, anything non-zero is considered True (this applies to ints, floats, and complex numbers). If you given Python a sequence or container, such as a list or string (which is a sequence of letters), then an empty sequence is considered False and a non-empty sequence is considered True:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Cat\n"
- ]
- }
- ],
- "source": [
- "print(\"\" or \"Cat\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To convert something into a boolean in the more classical sense, use the bool() function: "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(bool(\"\"))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(bool(\"Cat\"))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### In\n",
- "\n",
- "With many sequence or container-like objects, we can check for membership using in. For example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print('cat' in \"concatenate\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(\"dog\" in [\"cat\", \"dog\", \"hamster\"])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "# this is a set, a data structure we have not discussed.\n",
- "# sets contain unordered data with no duplicates\n",
- "# (identical entries are counted as a single entry)\n",
- "# They are occasionally useful.\n",
- "print(3 in {1, 2, 3})"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Identity: \"is\"\n",
- "\n",
- "We can check for two objects being actually the same object in Python's memory using is. This is, confusingly, different to using ==, which checks for some equality of value. This leads to some profoundly weird cases, especially with numbers and strings. Therefore the advice is to only use this in this in the situations I outline here. Let's see examples."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 17,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print([] is [])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Why did this evaluate False? Because writing an empty list [] always creates a brand new empty list. These are two different lists as far as Python is concerned. Hence is will come out as False. However:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print([] == [])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This comes out as True. While these are different lists, they have the same contents, and Python can see this. So, we use is when we want Python to check not just that two things look similar, but are one and the same object.\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 50,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n",
- "False\n"
- ]
- }
- ],
- "source": [
- "a = [\"spam\"]\n",
- "b = a\n",
- "c = [\"spam\"]\n",
- "print(a is b)\n",
- "print(c is a)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "There is one more use case I have found useful. This is for checking the None type object. None is a special object, representing nothing, nada. A function that gives no return value gives None:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 19,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "None\n"
- ]
- }
- ],
- "source": [
- "def gives_nothing():\n",
- " pass\n",
- "print(gives_nothing())"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "In many boolean situations, None is interpreted as False."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 23,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Was interpreted as False\n"
- ]
- }
- ],
- "source": [
- "probably_false = None\n",
- "if not probably_false:\n",
- " print(\"Was interpreted as False\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "However, None and False are certainly not the same. If I have a function that sometimes returns a value and sometimes does not, and I want to check if the function returned None, I can use is:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 30,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "gives_nothing() gave nothing\n"
- ]
- }
- ],
- "source": [
- "if gives_nothing() is None:\n",
- " print(\"gives_nothing() gave nothing\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 31,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "if gives_nothing() is not None:\n",
- " print(\"gives_nothing() gave something\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Looping over indices\n",
- "\n",
- "It is somewhat common, though to be avoided if feasible, to wish to loop over the indices of a list or other sequence, rather than the items of a list.\n",
- "\n",
- "There is a commonly used, naive way to do this. It is wrong, in the sense that it is ugly. Suppose I wish to print a list with numbering:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 33,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "1. Fruit\n",
- "2. Coffee\n",
- "3. Tofu\n",
- "4. Rice\n",
- "5. Soy sauce\n"
- ]
- }
- ],
- "source": [
- "shopping = [\"Fruit\", \"Coffee\", \"Tofu\", \"Rice\", \"Soy sauce\"]\n",
- "## Ugly version:\n",
- "for i in range(len(shopping)):\n",
- " list_item = \"{}. {}\".format(i+1, shopping[i]) \n",
- " print(list_item)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This is very common to see from both new and experienced programmers; in many programming languages, this kind of construction is the only way to perform this task. There is a much preferred method in Python, however:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 35,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "1. Fruit\n",
- "2. Coffee\n",
- "3. Tofu\n",
- "4. Rice\n",
- "5. Soy sauce\n"
- ]
- }
- ],
- "source": [
- "# Pythonic version\n",
- "for i, grocery in enumerate(shopping):\n",
- " list_item = \"{}. {}\".format(i+1, grocery)\n",
- " print(list_item)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "So, enumerate gives a sequence of tuples, the first being the index, the second being the element. Now we can use both. Fab!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 49,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[(0, 'Fruit'), (1, 'Coffee'), (2, 'Tofu'), (3, 'Rice'), (4, 'Soy sauce')]\n"
- ]
- }
- ],
- "source": [
- "print(list(enumerate(shopping)))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Break and continue\n",
- "\n",
- "We have yet two more tools to control the flow during loops.\n",
- "\n",
- "The break keyword can interrupt any loop, even if it has not yet run to completion. The code then continues running after the loop. This can be useful. Suppose we are searching a list for an entry that meets a certain condition. We may loop over the list and check each item for our desired criteria. If we find the item we are looking for, there is no need to continue searching the remainder of the list. Hence we will save time by running break.\n",
- "\n",
- "The statement works in both for-loops and while-loops. In the case of while loops, this means the loop can be told to run forever until break is executed."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 37,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "What is the capital of France? Huh?\n",
- "Try again!\n",
- "What is the capital of France? F\n",
- "Try again!\n",
- "What is the capital of France? Paris\n",
- "Well done!\n"
- ]
- }
- ],
- "source": [
- "while True: # True is always True, so this loop won't end until it hits a break!\n",
- " answer = input(\"What is the capital of France? \")\n",
- " if answer == \"Paris\":\n",
- " break\n",
- " else:\n",
- " print(\"Try again!\")\n",
- "\n",
- "print(\"Well done!\") # this is not in the loop (because of the indentation!)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "It also means that the \"checking\" phase of the loop, which checks whether the loop should continue running or stop and proceed to the next code block, can be placed at the beginning, middle or end of the loop, or even in multiple places. Usually a while-loop checks the condition at the beginning of the loop. But with a break, we can check at the end.\n",
- "\n",
- "The other control tool is continue. This keyword is again used inside a loop, and tells Python not to finish its current pass through the looped code, and instead continue to the next pass through, starting at the top again. This is syntactic sugar: a programming term which means a language element that is not strictly necessary, but makes it easier to type or express certain ideas. Virtually every continue could be replaced by re-arranging if statements, but sometimes continue just makes the whole thing easier and more readable.\n",
- "\n",
- "For now just pass your eyes over this toy example, and see if you can figure out what's going on:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 38,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "H\n",
- "i\n",
- "P\n",
- "y\n"
- ]
- }
- ],
- "source": [
- "for letter in \"Hello, we wish to learn Python\":\n",
- " if letter in \"and thus, where should we go?\":\n",
- " continue\n",
- " else:\n",
- " print(letter)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## For, else"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This is valid Python code:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 46,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Is a strictly ascending sequence\n",
- "Not strictly ascending\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "False"
- ]
- },
- "execution_count": 46,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "def strictly_ascending(seq):\n",
- " '''\n",
- " Check whether a sequence of values is in ascending order\n",
- " '''\n",
- " for i, x in enumerate(seq[1:]):\n",
- " if seq[i+1] <= seq [i]:\n",
- " print(\"Not strictly ascending\")\n",
- " break\n",
- " else:\n",
- " print(\"Is a strictly ascending sequence\")\n",
- " return True\n",
- " return False\n",
- " \n",
- "strictly_ascending([1, 2, 3, 6, 9])\n",
- "strictly_ascending([1, 2, 3, 3])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Most programmers double-take when they see this construction, and some prefer to avoid it altogether. A for-loop can be given an else clause, that executes only in the event that the for-loop ran to completion, and did not experience a break. This can be useful when searching through a list looking for an entry meeting certain conditions.\n",
- "\n",
- "Again, syntactic sugar. The same code could have been written:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 48,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Is a strictly ascending sequence\n",
- "Not strictly ascending\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "False"
- ]
- },
- "execution_count": 48,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "def strictly_ascending(seq):\n",
- " '''\n",
- " Check whether a sequence of values is in ascending order\n",
- " '''\n",
- " in_order = True\n",
- " for i, x in enumerate(seq[1:]):\n",
- " if seq[i+1] <= seq [i]:\n",
- " print(\"Not strictly ascending\")\n",
- " in_order = False\n",
- " break\n",
- " if in_order:\n",
- " print(\"Is a strictly ascending sequence\")\n",
- " return True\n",
- " return False\n",
- "\n",
- "strictly_ascending([1, 2, 3, 6, 9])\n",
- "strictly_ascending([1, 2, 3, 3])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Notice however, that this requires creating an extra variable to keep track of whether we found anything amiss. Which you use is up to you; I'm a fan of for-else -- sometimes it just feels like the right solution to a problem for me. Others disagree, with the belief that the construction is so peculiar to Python that it makes the code difficult to read for programmers who are not used to seeing it."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": true
- },
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.1"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/PurePy 8. Advanced Flow Control/.ipynb_checkpoints/Advanced Flow Control-checkpoint.ipynb b/PurePy 8. Advanced Flow Control/.ipynb_checkpoints/Advanced Flow Control-checkpoint.ipynb
deleted file mode 100644
index f4c0cd3..0000000
--- a/PurePy 8. Advanced Flow Control/.ipynb_checkpoints/Advanced Flow Control-checkpoint.ipynb
+++ /dev/null
@@ -1,728 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# More Flow Control\n",
- "\n",
- "So far, we have met if, elif and else, as well as for-loops and while-loops. Now we take a look at some more tools we have to control the behaviour of loops. Briefly before that though."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## The pass statement"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The statement pass is simply the \"do nothing\" statement. Including this somewhere in your code does precisely nothing. However, it is formally a valid Python statement. Therefore it can be used as a placeholder in a location where Python formally requires some code, but you either don't want to do anything, or simply haven't got round to it. For example, when you start designing a sequence of ifs and elifs, you may want to write out each possible choice ahead of writing out what to do in each case. Hence, we might write the Fizzbuzz challenge first like this:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "for x in range(100):\n",
- " if x % 3 == 0 and x % 5 == 0:\n",
- " pass\n",
- " elif x % 3 == 0:\n",
- " pass\n",
- " elif x % 5 == 0:\n",
- " pass\n",
- " else:\n",
- " pass"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This way, we can see some of the structure of the program, even we've not filled in the details yet. This is particularly useful when you are breaking your problem down into different functions; you can easily see what is yet to be done, especially when combined with doc strings."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "## example here"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## More logical checking tools\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Using other types as stand-ins for Booleans\n",
- "\n",
- "A neat thing about Python is that if we use a non-Boolean type in a logical expression, Python will have a go at interpreting it as a Boolean anyway.\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "0\n"
- ]
- }
- ],
- "source": [
- "print(1 and 0)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "1\n"
- ]
- }
- ],
- "source": [
- "print(1 and 1)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "In this case, Python knows to use 0 as False, and 1 as True. This works for all kinds of things, but the rule of thumb is this. If you give Python numbers in a boolean expression, 0 is considered False, anything non-zero is considered True (this applies to ints, floats, and complex numbers). If you given Python a sequence or container, such as a list or string (which is a sequence of letters), then an empty sequence is considered False and a non-empty sequence is considered True:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Cat\n"
- ]
- }
- ],
- "source": [
- "print(\"\" or \"Cat\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To convert something into a boolean in the more classical sense, use the bool() function: "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print(bool(\"\"))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(bool(\"Cat\"))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### In\n",
- "\n",
- "With many sequence or container-like objects, we can check for membership using in. For example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print('cat' in \"concatenate\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print(\"dog\" in [\"cat\", \"dog\", \"hamster\"])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "# this is a set, a data structure we have not discussed.\n",
- "# sets contain unordered data with no duplicates\n",
- "# (identical entries are counted as a single entry)\n",
- "# They are occasionally useful.\n",
- "print(3 in {1, 2, 3})"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Identity: \"is\"\n",
- "\n",
- "We can check for two objects being actually the same object in Python's memory using is. This is, confusingly, different to using ==, which checks for some equality of value. This leads to some profoundly weird cases, especially with numbers and strings. Therefore the advice is to only use this in this in the situations I outline here. Let's see examples."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 17,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n"
- ]
- }
- ],
- "source": [
- "print([] is [])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Why did this evaluate False? Because writing an empty list [] always creates a brand new empty list. These are two different lists as far as Python is concerned. Hence is will come out as False. However:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n"
- ]
- }
- ],
- "source": [
- "print([] == [])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This comes out as True. While these are different lists, they have the same contents, and Python can see this. So, we use is when we want Python to check not just that two things look similar, but are one and the same object.\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 50,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "True\n",
- "False\n"
- ]
- }
- ],
- "source": [
- "a = [\"spam\"]\n",
- "b = a\n",
- "c = [\"spam\"]\n",
- "print(a is b)\n",
- "print(c is a)\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "There is one more use case I have found useful. This is for checking the None type object. None is a special object, representing nothing, nada. A function that gives no return value gives None:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 19,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "None\n"
- ]
- }
- ],
- "source": [
- "def gives_nothing():\n",
- " pass\n",
- "print(gives_nothing())"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "In many boolean situations, None is interpreted as False."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 23,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Was interpreted as False\n"
- ]
- }
- ],
- "source": [
- "probably_false = None\n",
- "if not probably_false:\n",
- " print(\"Was interpreted as False\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "However, None and False are certainly not the same. If I have a function that sometimes returns a value and sometimes does not, and I want to check if the function returned None, I can use is:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 30,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "gives_nothing() gave nothing\n"
- ]
- }
- ],
- "source": [
- "if gives_nothing() is None:\n",
- " print(\"gives_nothing() gave nothing\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 31,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "if gives_nothing() is not None:\n",
- " print(\"gives_nothing() gave something\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Looping over indices\n",
- "\n",
- "It is somewhat common, though to be avoided if feasible, to wish to loop over the indices of a list or other sequence, rather than the items of a list.\n",
- "\n",
- "There is a commonly used, naive way to do this. It is wrong, in the sense that it is ugly. Suppose I wish to print a list with numbering:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 33,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "1. Fruit\n",
- "2. Coffee\n",
- "3. Tofu\n",
- "4. Rice\n",
- "5. Soy sauce\n"
- ]
- }
- ],
- "source": [
- "shopping = [\"Fruit\", \"Coffee\", \"Tofu\", \"Rice\", \"Soy sauce\"]\n",
- "## Ugly version:\n",
- "for i in range(len(shopping)):\n",
- " list_item = \"{}. {}\".format(i+1, shopping[i]) \n",
- " print(list_item)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This is very common to see from both new and experienced programmers; in many programming languages, this kind of construction is the only way to perform this task. There is a much preferred method in Python, however:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 35,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "1. Fruit\n",
- "2. Coffee\n",
- "3. Tofu\n",
- "4. Rice\n",
- "5. Soy sauce\n"
- ]
- }
- ],
- "source": [
- "# Pythonic version\n",
- "for i, grocery in enumerate(shopping):\n",
- " list_item = \"{}. {}\".format(i+1, grocery)\n",
- " print(list_item)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "So, enumerate gives a sequence of tuples, the first being the index, the second being the element. Now we can use both. Fab!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 49,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[(0, 'Fruit'), (1, 'Coffee'), (2, 'Tofu'), (3, 'Rice'), (4, 'Soy sauce')]\n"
- ]
- }
- ],
- "source": [
- "print(list(enumerate(shopping)))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Break and continue\n",
- "\n",
- "We have yet two more tools to control the flow during loops.\n",
- "\n",
- "The break keyword can interrupt any loop, even if it has not yet run to completion. The code then continues running after the loop. This can be useful. Suppose we are searching a list for an entry that meets a certain condition. We may loop over the list and check each item for our desired criteria. If we find the item we are looking for, there is no need to continue searching the remainder of the list. Hence we will save time by running break.\n",
- "\n",
- "The statement works in both for-loops and while-loops. In the case of while loops, this means the loop can be told to run forever until break is executed."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 37,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "What is the capital of France? Huh?\n",
- "Try again!\n",
- "What is the capital of France? F\n",
- "Try again!\n",
- "What is the capital of France? Paris\n",
- "Well done!\n"
- ]
- }
- ],
- "source": [
- "while True: # True is always True, so this loop won't end until it hits a break!\n",
- " answer = input(\"What is the capital of France? \")\n",
- " if answer == \"Paris\":\n",
- " break\n",
- " else:\n",
- " print(\"Try again!\")\n",
- "\n",
- "print(\"Well done!\") # this is not in the loop (because of the indentation!)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "It also means that the \"checking\" phase of the loop, which checks whether the loop should continue running or stop and proceed to the next code block, can be placed at the beginning, middle or end of the loop, or even in multiple places. Usually a while-loop checks the condition at the beginning of the loop. But with a break, we can check at the end.\n",
- "\n",
- "The other control tool is continue. This keyword is again used inside a loop, and tells Python not to finish its current pass through the looped code, and instead continue to the next pass through, starting at the top again. This is syntactic sugar: a programming term which means a language element that is not strictly necessary, but makes it easier to type or express certain ideas. Virtually every continue could be replaced by re-arranging if statements, but sometimes continue just makes the whole thing easier and more readable.\n",
- "\n",
- "For now just pass your eyes over this toy example, and see if you can figure out what's going on:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 38,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "H\n",
- "i\n",
- "P\n",
- "y\n"
- ]
- }
- ],
- "source": [
- "for letter in \"Hello, we wish to learn Python\":\n",
- " if letter in \"and thus, where should we go?\":\n",
- " continue\n",
- " else:\n",
- " print(letter)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## For, else"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This is valid Python code:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 46,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Is a strictly ascending sequence\n",
- "Not strictly ascending\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "False"
- ]
- },
- "execution_count": 46,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "## NEEDS A BETTER EXAMPLE, THIS ONE IS ENTIRELY USELESS\n",
- "\n",
- "def strictly_ascending(seq):\n",
- " '''\n",
- " Check whether a sequence of values is in ascending order\n",
- " '''\n",
- " for i, x in enumerate(seq[1:]):\n",
- " if seq[i+1] <= seq [i]:\n",
- " print(\"Not strictly ascending\")\n",
- " break\n",
- " else:\n",
- " print(\"Is a strictly ascending sequence\")\n",
- " return True\n",
- " return False\n",
- " \n",
- "strictly_ascending([1, 2, 3, 6, 9])\n",
- "strictly_ascending([1, 2, 3, 3])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Most programmers double-take when they see this construction, and some prefer to avoid it altogether. A for-loop can be given an else clause, that executes only in the event that the for-loop ran to completion, and did not experience a break. This can be useful when searching through a list looking for an entry meeting certain conditions.\n",
- "\n",
- "Again, syntactic sugar. The same code could have been written:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 48,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Is a strictly ascending sequence\n",
- "Not strictly ascending\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "False"
- ]
- },
- "execution_count": 48,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "def strictly_ascending(seq):\n",
- " '''\n",
- " Check whether a sequence of values is in ascending order\n",
- " '''\n",
- " in_order = True\n",
- " for i, x in enumerate(seq[1:]):\n",
- " if seq[i+1] <= seq [i]:\n",
- " print(\"Not strictly ascending\")\n",
- " in_order = False\n",
- " break\n",
- " if in_order:\n",
- " print(\"Is a strictly ascending sequence\")\n",
- " return True\n",
- " return False\n",
- "\n",
- "strictly_ascending([1, 2, 3, 6, 9])\n",
- "strictly_ascending([1, 2, 3, 3])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Notice however, that this requires creating an extra variable to keep track of whether we found anything amiss. Which you use is up to you; I'm a fan of for-else -- sometimes it just feels like the right solution to a problem for me. Others disagree, with the belief that the construction is so peculiar to Python that it makes the code difficult to read for programmers who are not used to seeing it."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": true
- },
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.5.2"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/PurePy 9. Advanced Functions/.ipynb_checkpoints/9.0 Advanced Functions and Functional Programming-checkpoint.ipynb b/PurePy 9. Advanced Functions/.ipynb_checkpoints/9.0 Advanced Functions and Functional Programming-checkpoint.ipynb
deleted file mode 100644
index 7ed7e1e..0000000
--- a/PurePy 9. Advanced Functions/.ipynb_checkpoints/9.0 Advanced Functions and Functional Programming-checkpoint.ipynb
+++ /dev/null
@@ -1,785 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "In this article we're gonna cover a lot of ground. So far we have seen that functions can be used to encapsulate tasks we want to perform throughout our programs. They take some input, perform some computation, and then give us an output. We're now going to explore a number of powerful concepts involving functions, culminating in a brief discussion of functional programming, a programming paradigm that is quite different to the methodology we have used so far.\n",
- "\n",
- "## First-class objects\n",
- "\n",
- "We've not got around to a proper discussion of objects yet. But they're all around us. A number is an object, a string is an object, a list is an object. Basically anything you can assign to a variable or pass to a function or get out of a function is an object.\n",
- "\n",
- "Well, turns out functions are objects too. You can assign functions to variables, use functions as arguments to functions, and even return functions from functions.\n",
- "\n",
- "We've actually briefly seen this before. In a previous video, we used the max() function to determine the maximum entry of a dictionary by value rather than by key. For this, we had to pass the get function to max, which gets the value from the key, to make the max() function behave in this way.\n",
- "\n",
- "Some of the concepts here will be based on this possibly surprising fact about functions.\n",
- "\n",
- "## Recursion\n",
- "\n",
- "An interesting fact about functions is that they can be called within their own definitions. This is useful for a surprising number of algorithms, and can sometimes lead to nicer code than loops. Just like with while-loops though, you have to make sure there is some point at which the functions stop calling and start returning values! This is called the \"base case\". A recursive function calls itself until it reaches the base case."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "514229"
- ]
- },
- "execution_count": 9,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "def fib(n):\n",
- " # get the nth fibonacci number\n",
- " if n == 1:\n",
- " return 0\n",
- " elif n == 2:\n",
- " return 1\n",
- " else:\n",
- " return fib(n-1) + fib(n-2)\n",
- " \n",
- "fib(30)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The deal with recursion is that some problems are the sum of several smaller problems of the same kind. For example, a lot of searching problems, where we are searching for some item in a structure such as a file system, network or list, can be conceived of as searching through many sub-structures within that structure. For instance, searching for a file in a directory involves searching through sub-directories of that directory, which involves searching through sub-directories of the sub-directories, and so on. This complicated task can be accomplish with a recursive algorithm."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercises\n",
- "\n",
- "1. Look up the binary search algorithm and write a recursive function to implement it.\n",
- "2. (Mathematical, challenging) Laplace's algorithm for finding the determinant of a square matrix is recursive. Write a function that can take a square matrix as a list of lists and find its determinant using the recursive Laplace algorithm."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Lambda expressions\n",
- "\n",
- "Functional programming is based on the formal mathematical system called the lambda calculus. A vestige of this origin lives on in so-called lambda expressions. This somewhat intimidating-sounding name is actually very simple. As one of the Python developers once said, if lambda were called \"makefunction\", no one would be confused. A lambda expression consists solely of one or more inputs, followed by a return statement. Here is a simple lambda expression that squares a number:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- ">"
- ]
- },
- "execution_count": 10,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "lambda x : x**2"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This is a complete description of a function. The variable x goes in, x**2 comes out. The function consists of a single return expression. There can be no variable assignments or references; the function is solely defined by input and output. The function has no name attached to it, but it can still be assigned to a variable:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 22,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "100\n"
- ]
- }
- ],
- "source": [
- "square = lambda x : x**2\n",
- "print(square(10))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 42,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "125"
- ]
- },
- "execution_count": 42,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "power = lambda x, n: x**n\n",
- "power(5, 3)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "So, why lambdas? Sometimes, it's just quicker and easier to use lambdas. Suppose I want a function that tells me the number of digits in an integer:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "digits = lambda x: len(str(x))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "7"
- ]
- },
- "execution_count": 15,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "digits(4343452)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Another primary use case is for functions that take a function as an argument, but the function you want to pass is too simple to be worth building separately."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Suppose I have a list of 2d vectors, represented as pairs of numbers. The norm of a vector $(a, b)$ is given by the Pythagorean formula $\\sqrt{a^2 + b^2}$. We wish to find the vector with the largest norm."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 33,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "# first make some random vectors\n",
- "from random import uniform\n",
- "vectors = [(uniform(-50, 50), uniform(-50, 50)) for x in range(20)]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 38,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(-45.3519046167027, 47.28755575244766)\n"
- ]
- }
- ],
- "source": [
- "# find vector with largest norm:\n",
- "largest = max(vectors, key= lambda v: (v[0]**2 + v[1]**2)**0.5)\n",
- "print(largest)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Recall that the key argument provided to the max() function tells max() what method to use to measure the maximum. It must be a function. But instead of defining the function using the normal syntax, it was quicker and easier to write a little lambda function in that argument slot. The .sort() method that can be applied to lists can also take a key argument, so lambda expressions can be useful here too. "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Exercises\n",
- "\n",
- "Write a lambda function that acts as an XOR logical operator. XOR stands for \"exclusively or\", and evaluates to true only when one of its arguments is true, but the other isn't. \"One, the other, but not both\". In other words, correctly define the XOR variable using a lambda function in this example so that the code runs:\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 52,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "False\n",
- "True\n",
- "True\n",
- "False\n"
- ]
- }
- ],
- "source": [
- "#XOR = your lambda expression here\n",
- "print(XOR(True, True))\n",
- "print(XOR(False, True))\n",
- "print(XOR(True, False))\n",
- "print(XOR(False, False))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "(Challenge) Write a lambda function that returns a new lambda function for raising an input to a chosen power. Again, correctly define the following variable so that the code runs:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 50,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "25\n",
- "125\n",
- "0.2\n"
- ]
- }
- ],
- "source": [
- "# raiseto = your lambda here\n",
- "square = raiseto(2)\n",
- "print(square(5))\n",
- "cube = raiseto(3)\n",
- "print(cube(5))\n",
- "invert = raiseto(-1)\n",
- "print(invert(5))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## \\*args and \\**kwargs\n",
- "\n",
- "In the introduction to functions, we saw that we had a choice between using positional arguments, and keyword arguments.\n",
- "\n",
- "Sometimes we may want a function that can take arbitrary collections of arguments. For instance, the max() can take an arbitrary number of positional arguments before accepting a keyword argument:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "# the abs() function gives the number's absolute value -- in this case, ignores the minus sign\n",
- "print(max(1, -5, 3, 4, -2, key=abs))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Our own functions can match this behaviour, using a \\* symbol. A function parameter with a \\* at the beginning is understood to be a sequence of arguments of an unknown length."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "1. Apples\n",
- "2. Bananas\n",
- "3. Pears\n"
- ]
- }
- ],
- "source": [
- "def number_my_sequence(*seq):\n",
- " for i, thing in enumerate(seq):\n",
- " print(\"{}. {}\".format(i+1, thing))\n",
- " \n",
- "number_my_sequence(\"Apples\", \"Bananas\", \"Pears\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "There is something of an opposite notion; when calling a function, if an argument is preceded by the \\*, then if it is sequence-like, it will be \"unpacked\" before the function is called. Look carefully at the example. The adder function takes two arguments. We pass it just one argument, which is a sequence with two elements to be unpacked to form the two arguments:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "11\n"
- ]
- }
- ],
- "source": [
- "def adder(a, b):\n",
- " return a + b\n",
- "numbers = [5, 6]\n",
- "print(adder(*numbers))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "There is an equivalent syntax for keyword arguments. A \\*\\* added to the beginning of a parameter means that the keyword arguments provided here will be expanded to a dictionary:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "{'name': 'Sam', 'working_with': 'HiPy'}\n"
- ]
- }
- ],
- "source": [
- "def kwarg_example(**things):\n",
- " print(things)\n",
- " \n",
- "kwarg_example(name=\"Sam\", working_with=\"HiPy\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The reverse syntax also applies as above, in that a dictionary can be expanded into keyword arguments with keys as keywords and values as arguments."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Iterators and generators\n",
- "\n",
- "A brief bit of theoretical woffle before we get to the upshot. You have probably noticed that for-loops can be used on many different kinds of objects, such as ranges, lists, strings, tuples, dictionaries, and many others. Objects that can be looped over are called \"iterable\". When placed in the context of a for-loop, they become an iterator, which means they know what to do each time the for-loop asks for the next item. We can actually do this manaully. Firstly, observe that at first, Python does not know what \"next\" means in terms of a string:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 54,
- "metadata": {},
- "outputs": [
- {
- "ename": "TypeError",
- "evalue": "'str' object is not an iterator",
- "output_type": "error",
- "traceback": [
- "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)",
- "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[0mpythonclub\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;34m\"HiPy\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0mnext\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mpythonclub\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[1;31mTypeError\u001b[0m: 'str' object is not an iterator"
- ]
- }
- ],
- "source": [
- "pythonclub = \"HiPy\"\n",
- "print(next(pythonclub))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "However, we can ask the string to give us an iterator:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 55,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "iterclub = iter(pythonclub)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now we can ask for the next value:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 56,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "H\n"
- ]
- }
- ],
- "source": [
- "print(next(iterclub))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 57,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "i\n"
- ]
- }
- ],
- "source": [
- "print(next(iterclub))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 58,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "P\n"
- ]
- }
- ],
- "source": [
- "print(next(iterclub))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 59,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "y\n"
- ]
- }
- ],
- "source": [
- "print(next(iterclub))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 60,
- "metadata": {},
- "outputs": [
- {
- "ename": "StopIteration",
- "evalue": "",
- "output_type": "error",
- "traceback": [
- "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[1;31mStopIteration\u001b[0m Traceback (most recent call last)",
- "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnext\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0miterclub\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[1;31mStopIteration\u001b[0m: "
- ]
- }
- ],
- "source": [
- "print(next(iterclub)) # we're out of letters!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "So what a for-loop does is ask the object (string, list, range, etc) we provide for an iterator, and then use next on the object until it runs out.\n",
- "\n",
- "We'll discuss this point in more detail when we discuss object-oriented programming. But for now, in our discussion of functions, we can make a special kind of function that is iterable. In other words, the function can give a sequence of different outputs when placed in the context of a for-loop. A generator looks exactly like a normal function, but instead of the word return returning a value, the word yield is used instead. When the generator \"yields\" something, it stops until something asks it for the next value, in which case, it picks up exactly where it left off!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 67,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "from random import randint # for random integers\n",
- "def random_numbers(count, low=0, high=100):\n",
- " for i in range(count):\n",
- " yield randint(low, high) "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 68,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Next number is 68\n",
- "Next number is 72\n",
- "Next number is 88\n",
- "Next number is 0\n",
- "Next number is 47\n",
- "Next number is 36\n",
- "Next number is 73\n",
- "Next number is 52\n",
- "Next number is 95\n",
- "Next number is 3\n"
- ]
- }
- ],
- "source": [
- "for x in random_numbers(10):\n",
- " print(\"Next number is\",x)\n",
- " "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The enumerate() function we met in the previous article on Flow Control is somewhat equivalent to:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "1. Chickpeas\n",
- "2. Onions\n",
- "3. Flatbread\n"
- ]
- }
- ],
- "source": [
- "def fake_enumerate(seq):\n",
- " for i in range(len(seq)):\n",
- " yield i, seq[i]\n",
- " \n",
- "shopping = [\"Chickpeas\", \"Onions\", \"Flatbread\"]\n",
- "\n",
- "for k, grocery in fake_enumerate(shopping):\n",
- " print(\"{}. {}\".format(k+1, grocery))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Notice, inside the generator there is a for-loop, but one that can be put on pause until the outer for-loop (for k, grocery in fake_enumerate(shopping):) asks it to carry on. This is quite mindbending, but it can be useful. In the example, we use a generator to convert some real genetic data from a text file into a more Python-friendly format."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "image/jpeg": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkz\nODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2MBERISGBUYLxoaL2NCOEJjY2NjY2NjY2Nj\nY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY//AABEIAWgB4AMBIgACEQED\nEQH/xAAbAAEAAwEBAQEAAAAAAAAAAAAAAgMEAQUGB//EAEUQAAIBAwIDBgQEBAMGBQQDAAECAwAE\nERIhEzFBBRQiUWFxMoGRoQYVI7E0QnLBJNHwM1JTYpLhNUOisvElY4LCVHPS/8QAFwEBAQEBAAAA\nAAAAAAAAAAAAAAECA//EACARAQACAQQDAQEAAAAAAAAAAAABERICEyExAyJhQVH/2gAMAwEAAhED\nEQA/APz+lKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUC\nlKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUC\nlKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUC\nlKUClKUClKUClKUClKUClaBZysQBpyRnnXWsZkGWAA96tSzlDNStIspiSAASPKuGylBAOBnlSpMo\nZ6VpWxmbkM9K4LOUgnbY4pUmUM9K0mymUZOAKCxmJIABI50qTKGalaO5y5I2yBk+lBZTHkufrSpM\noZ6Vf3SXfltzqRsZhzFKkyhmpV/dJNIbbBOM1zuz+a0qTKFNKu7s/mtO7P5rSpMoU0q7uz+a07s/\nmtKkyhTSru7P5rTuz+a0qTKFNKu7s/mtO7P5rSpMoU0q7uz+a07s/mtKkyhTStadm3LoGVMq3I+d\ncWwncqFUHVnT61FyhlpWprCdQSwAA570awnUgMFBIyN6JlDLSth7MuQuSgx55qtbOV/hwceVI56M\noZ6VpaxmUgMACa4LKUjIxj3q1JlDPStPcZsgYGTyrgspiSABkc6VJlDPStBs5VODgGpHs+4AJKgA\nUqTKGWlaVsZmAIAINc7nLnHhz70qTKGelaDZyg42z5UNlMDggZxmoZQz0q/ukm3LflUu4zaguBqI\n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\nv4c/jJ/6F/evLwcZwa9T8Ofxk/8AQv70GOOzjaBWN/pJjZivFGz7aRj2/auNBHxl4sszqJVTPHHh\nXo/L1+VeM/xn3rmDQh7C20fdFlS4kZiC3AEwBGD4d/Qb/KgW1aVkWaaPxIuvjA7MN+npivHIIqaw\nSNHrC+Hc5zQevLHbx5SSSUvofUBcZHhGw5epqxbGIIc9pEalTIEo3bPj+nOvApQe7HbBYQ4upUkD\ns3AE4znBxv57HeoLHDFqHeJlLKgEomGGBO+3kPL0rxaUHti3xccJL94AhBYcTVg42I5dNvTFZYjm\nC6kSWYSRRjL69idWCPbevOrupgpUE6TzGaCwXM4QpxpNJ5jUcGpC8uRyuJRzHxnrzqilBct1cKML\nPIBkHZj0p3u4/wCPL1/nPXnVNKC43VwSCZpDpGB4jt/rFO93Acvx5dR66zmqaUFhuJmI1SucYxlj\ntjlUmu7hgQ08pydRy55+dU0oLu93GnHHlxjTjWeXlXDczF2cyyam5nUcmqqUFouZxymk55+I866t\n1cIAFnkUA5ADHY1TSguN3cHTmeQ6TkeI7VwXM4IImkBHLxHaqqUF3e7n/jy9f5z15/WuNcTOQWlk\nYjGCWO2OVVUoLUuZ41CpNIoXOAGIxnnXTdTnGZpDgaR4jsPKqaUFq3MyuHWWQMNgQxyK9z8IMW7S\nlLEk8NRv/UK+er3/AMH/APiEv9A/9woM8PaoiRo3y40hMY5DIz+1X/nFmHVkt8ENn4V5Yx5V4ROS\nTXKlLb3k7VsBCVNvlsbZUVFu1rQumm3AUHLZQZIrw6Uot69x2hZyxoqQmMrncDc+9W3HadmQzQR6\nXDeA6cYGc5/YV4dKUW9W27SjiuTNJqYkHOOuavuu1rS6RVKOmnGCPv8AvXh0pRb17TtG3tblnwzp\nggedaF7cgCYaIudIB1cjivApSi3sRdpWy3jSyxtMjDk/OuN2nAdQEQUaQFwg2Ix/3ryKUot735za\ntIS8AZeIXAKDqKzXXaFvME4cQj0+Q58v+9eVSlFtveY/M/SneY/M/SsVKqNveY/M/SneY/M/SsVK\nDb3mPzP0p3mPzP0rFSg295j8z9Kd5j8z9KxUoPc/N7fg8L9Ugx6MHz86Qdq21uNKGUqHJ9xgj5V4\ndKlLbc11EWJGQCeVc7zH5n6VipVRt7zH5n6VbbX0MM6SMCwU5x69K82lB7T9q27E4VwCjrj3OR+9\nbPwy6yXVwV5aF/evma29mdpzdmPI0KRuXAB1gnH0IoKnlUZUrnGRvXbadYWVmGdLZx57VnJySfOu\nVKhnGKpfPKsjZXON9jvipI8fBXMgBVGGnBzvms1KscLEUUpSilKUoFKUoFKUoFKUoFKUoFKUoFKU\noFKUoFKUoFKUoFKUoFe/+D//ABCX+gf+4V4FbezO0pezJ2lhSNywxiQEjnnoR5UGKlKUClKUClKU\nClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKU\nClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKU\nClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKU\nClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKU\nClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUClKUH//Z\n",
- "text/html": [
- "\n",
- " \n",
- " "
- ],
- "text/plain": [
- ""
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "from IPython.display import YouTubeVideo\n",
- "YouTubeVideo(\"M-brh-eFgyE\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Functional Programming\n",
- "\n",
- "Here, we will just introduce the very basic concept of functional programming, as something to chew over and consider in your own program designs. So far, what we have been doing is what is called imperative programming. The program has a state, which means it holds some things in memory, usually in the form of variables, and we proceed by updating the program's state by changing these variables, reassigning them, and so on. At the top of this article, we used recursion to find the $n$th fibonacci number. Let's now do it in a pure imperative style:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 69,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "514229\n"
- ]
- }
- ],
- "source": [
- "n = 30\n",
- "for k in range(n):\n",
- " if k < 2:\n",
- " x = 0\n",
- " y = 1\n",
- " else:\n",
- " # to understand this line, remember that when assigning variables\n",
- " # the right hand side is fully evaulated before being assigned to the LHS\n",
- " x, y = y, x + y\n",
- "print(y)\n",
- " "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "This program achieves the same task, but we first set n to something. Then we iterate over k, and for each k, update two variables x and y. At each pass through the loop, the state of the program is changed; k, x, and y are all modified\\*. That is imperative programming in a nutshell."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "While imperative programming is easy to get going with, it's also easy to get in a tangle with. Because different functions are constantly referring to and altering different parts of a (large) program's state, it's very easy for errors to occur because some part of the program's state is wrong at the time a particular function or operation is executed.\n",
- "\n",
- "Functional programming aims to fix this by encouraging a very different style of design. Functional programming demands that we make our functions behave like mathematical functions, in that there is one, and only one, possible output for each input to a function. In imperative programming, the function may behave differently at different times with the same inputs, because the program's state is different at those different times. Moreover, the function may alter the program's state, which can cause other functions to behave differently at a later time. This is the concept of \"side-effects\".\n",
- "\n",
- "In functional programming, the program does not have a state. It has functions, which behave in exactly the same way every time they are called with the same inputs, guaranteed. Each function has an input, and an output, and nothing that goes on inbetween can have any effect on, or be affected by, the rest of the program's behaviour. Check out the recursive fibonacci program; there's not a variable in sight. Just functions taking inputs and returning values. This leads to essentially bug-free code, so long as the functions are correctly defined and applied in the correct order. \n",
- "\n",
- "Functional programming isn't easy, but Python does have some support to make it easier via the functools module. While some programming languages are purely functional, Python is multi-paradigm, and the good thing about functional programming in Python is it needn't be all or nothing. It can fit around the rest of your program design. After all, the whole point of functional programming is \"no side effects\"! Thus if you find that you can solve one of your problems by writing a function that neither affects nor is affected by the program's state, but only by its input values, then why not go ahead and do it that way, reaping some of the benefits of functional programming as you do?\n",
- "\n",
- "For some specific examples of functional programming techniques in Python, see this article https://maryrosecook.com/blog/post/a-practical-introduction-to-functional-programming\n",
- "Note that the examples are in Python 2, which means print() does not need the brackets. Also, the author uses map(), filter a lot; in Python 3 it is generally considered preferable to use list comprehensions to perform the same task.\n",
- "\n",
- "\\* This is a subtle point about for-loops easily missed. The variable that gets bound at the start of each pass through, such as the x appearing in the line for x in range(10), remains assigned even after the loop is finished running. Therefore, as far as functional programming goes, it constitutes a side-effect -- the state of the program is changed. The same is not true of the \"for loops\" found in list comprehensions; these are side-effect free."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.1"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 1
-}
diff --git a/[BASICS] Getting Started With Python 1 - The Basics/.ipynb_checkpoints/Getting Started In Python 1 - The Basics-checkpoint.ipynb b/[BASICS] Getting Started With Python 1 - The Basics/.ipynb_checkpoints/Getting Started In Python 1 - The Basics-checkpoint.ipynb
deleted file mode 100644
index b88f08c..0000000
--- a/[BASICS] Getting Started With Python 1 - The Basics/.ipynb_checkpoints/Getting Started In Python 1 - The Basics-checkpoint.ipynb
+++ /dev/null
@@ -1,618 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- ""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Congratulations on getting set up with Python! If you're not familiar with programming then don't worry; you have already done the hardest part. Python is one of the easiest programming languages to get into due to simple syntax (how your code is written), and a highly active community (hello!) - but can be built upon extensively to perform complex data analysis, create websites, and automate typically difficult jobs to be done quickly and efficiently.\n",
- "\n",
- "In this guide we're going to go over some critical programming concepts to understand, and then move onto creating a simple graph using a library we'll spend a lot of time with - matplotlib. Let's go!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Programming Basics"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To start, we need to talk very generally about objects. An object can be generally be thought as a piece of information, such as a number, word, or sentence. Later on we'll see some more complex examples of objects (and eventually how to define our own!) but for now let's look at some simple ones. Since sometimes we want to store an object in our computer's memory to recall later, we can assign an object a label. We call this label a variable."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [],
- "source": [
- "myVariable = 30"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To recall this variable's value, we can use the print function:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "30\n"
- ]
- }
- ],
- "source": [
- "print(myVariable)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Variables are especially helpful when the object we want to asign them to are very large. Imagine having a dataset of millions of values; it would be very fustrating to write it all out again and again! Another important property of variables is they act just like the object they were assigned to."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [],
- "source": [
- "apples = 4\n",
- "oranges = 6"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "10\n"
- ]
- }
- ],
- "source": [
- "print(apples + oranges)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can assign any object to a variable - since the sum of our two variables above is an object (a number), we can assign it a name."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [],
- "source": [
- "fruits = apples + oranges"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "10\n"
- ]
- }
- ],
- "source": [
- "print(fruits)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": true
- },
- "source": [
- "So far, we've only looked at whole numbers being stored as variables. In Python, these are called integers or int. For any variable, we can check the type by using the type() function:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n"
- ]
- }
- ],
- "source": [
- "print(type(fruits))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Later we'll see how to define our own types, but let's look at some of the more common ones. First off we have floating point numbers."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "6.283\n"
- ]
- }
- ],
- "source": [
- "myFloat = 3.1415\n",
- "\n",
- "print(myFloat * 2)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We also have strings, which are just characters, words, or phrases:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Hello Python!\n"
- ]
- }
- ],
- "source": [
- "myString = \"Hello Python!\"\n",
- "\n",
- "print(myString)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "It's worth noting that every type has it's own attributes - we can't add two words the same way we can numbers, but Python treats adding two strings together by joining them:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Hello Python! Hello World!\n"
- ]
- }
- ],
- "source": [
- "print(myString + \" Hello World!\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Next, we have Boolean or Bool variables. These can either be True or False. These are seen everywhere, most of the time behind the scenes, but it's important to know how they work as we can often use them to do some sneaky tricks to improve our code."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {},
- "outputs": [],
- "source": [
- "myBool = True"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Finally, for now, we have lists. Lists contain elements, that in themselves are objects:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [],
- "source": [
- "myList = [1, 3.24, \"string\", False]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To pull out items from our list, we use indexing:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "3.24\n"
- ]
- }
- ],
- "source": [
- "print(myList[1])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Indexing starts at 0, so the index 1 here takes the second element out of our list. Although this might seem unintuitive (and is a source for a lot of my errors!), there are a lot of good reasons for doing this - "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can also take slices from the list, to form new lists:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[1, 3.24, 'string']\n"
- ]
- }
- ],
- "source": [
- "myList2 = myList[0:3]\n",
- "print(myList2)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Slices start at the first index, and end before the last index. Again, confusing and annoying at first, but sometimes we can use it in tricky ways to speed code up."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Like, strings, lists have some unique attributes - one example is the append() method, and more can be found in the Python documentation [here](https://docs.python.org/3/tutorial/datastructures.html). The append method is simple, it takes whatever's in the brackets and adds it to the list in question:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[1, 3.24, 'string', False, True]\n"
- ]
- }
- ],
- "source": [
- "myList.append(True)\n",
- "print(myList)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To check the length of a list, we use the len() function:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "5\n"
- ]
- }
- ],
- "source": [
- "print(len(myList))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Finally, let's go back and take a look at some operators we missed. +, -, *, / work as expected, but it's helpful to know some others. ** is for powers, // for floor division, or division without remainder, and % for modulo, or division with just the remainder:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 17,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "9\n",
- "2\n",
- "1\n"
- ]
- }
- ],
- "source": [
- "print(3 ** 2) # 3 Squared\n",
- "print(5 // 2) # 5 divided by 2 without remainder\n",
- "print(13 % 3) # The remainder of 13 divided by 3"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Importing Modules"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Python comes with loads of functions, and we've already seen some (print, len), but sometimes we want to do more complicated things. The great thing about Python is its huge community creating tools for everyone to use. These tools usually come in packages called modules or libraries, that we can download and import to Python. If you're using Anaconda, or Azure Notebooks, almost all of the modules we use come pre-installed, so all we need to do is import them. To do this, we use the syntax:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "import matplotlib"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To use a fuction from matplotlib, a graphical plotting library, we would have to type matplotlib.pyplot.plot(). However, as this is a bit long-winded, Python lets us shorten these names and import them under an alias as follows:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 19,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "import matplotlib.pyplot as plt"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now, instead of typing matplotlib.pyplot.plot(), we just need to type plt.plot(). Let's look at how we can use matplotlib to create some simple visualisations."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "First, we need some data. For this we are going to create two lists - one of the numbers 1 to 10, and another of their squares: "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 20,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "x = [1,2,3,4,5,6,7,8,9,10]\n",
- "y = [1,4,9,16,25,36,49,64,81,100]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Plotting of these is simple - we just run the plot function above with x and y as inputs, or arguments, and then use the plt.show() function to show the plot:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 21,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "image/png": "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\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "plt.plot(x,y)\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Great! Later on we will see how to edit these graphs, adding titles, labels to the x and y axis, and changing the color of the line and background."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "For now, that's it! In the next guide we'll look more into the programming side of things - how we can write code to automate boring tasks, and create the building blocks to make bigger programs."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Worked Example"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "In this section, we'll look at a full piece of sample code, and explain it. Feel free to edit this and see what happens!\n",
- "\n",
- "Here we are looking at the stock price of Apple over Feburary 2017.\n",
- "\n",
- "First we import the required library, then set up our data, and finally, plot it."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 22,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "image/png": "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\nlgeoR7cAAAAASUVORK5CYII=\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "import matplotlib.pyplot as plt\n",
- "\n",
- "prices = [128.750000, 128.529999, 129.080002,130.289993,131.529999,132.039993,132.419998,132.119995,133.289993,135.020004,135.509995,135.350006,135.720001,136.699997,137.110001,136.529999,136.660004,136.929993,136.990005]\n",
- "days = [1,2,3,6,7,8,9,10,13,14,15,16,17,21,22,23,24,27,28]\n",
- "\n",
- "plt.plot(days,prices)\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Mini Project"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "In this section, we'll give you something to do, to give you some practice if needed. Similar to the worked example, here's the data for the mean temperature in celsius each month over 2016 - can you graph it using matplotlib?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "temperatures = [4.5,3.9,5.3,6.5,11.3,13.9,15.3,15.5,14.6,9.8,4.9,5.9]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.6"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/[BASICS] Getting Started With Python 2 - The Basics/.ipynb_checkpoints/Getting Started With Python 2 - The Basics-checkpoint.ipynb b/[BASICS] Getting Started With Python 2 - The Basics/.ipynb_checkpoints/Getting Started With Python 2 - The Basics-checkpoint.ipynb
deleted file mode 100644
index b18a219..0000000
--- a/[BASICS] Getting Started With Python 2 - The Basics/.ipynb_checkpoints/Getting Started With Python 2 - The Basics-checkpoint.ipynb
+++ /dev/null
@@ -1,685 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- ""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Python as a Programming Language"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "So far we've seen Python do some very simple things, that software like Excel could do just as well. What sets Python apart from other programming languages and software is it's ability to easily make automated programs quickly. Here we will look at the building blocks of writing programs, and think about how we can use them in a real environment."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## A Deeper Look Into Functions"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Functions are an integral part of Python - throughout your time with Python you will use many functions written by other people, and hopefully some you write yourself. A function can take in arguements as inputs, then performs a process, and then returns an output. Let's take a look at the pow() function to see what's going on:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "81\n"
- ]
- }
- ],
- "source": [
- "print(pow(3,4))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The pow() function takes in two arguements, and returns the first arguement to the power of the second. Let's take a look at how to write this function ourselves:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [],
- "source": [
- "def myPow(a,b):\n",
- " return a ** b"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The most important thing to remember here is the whitespace between the left margin and the second line; Python cares about indentations. In function definitions, we declare the name and arguements of a function, and then write the process, and what to return in an indented block. The names of the arguements don't matter - they are just dummy variables, used to give Python an example of what to do."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "You might have noticed instead of printing you can just output the variable straight away:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "3"
- ]
- },
- "execution_count": 1,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a = 3\n",
- "a"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What does this have to do with functions? The number one problem with function definitions is not knowing the difference between return and print. A function can only \"return\" one thing - when the function returns something, it ends, because the output has been reached. A function can \"print\" as many things as it wants - but won't treat these as outputs. This can lead to some interesting errors - let's look at what happens when we chain functions together written with print:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [],
- "source": [
- "def myAdd(a,b):\n",
- " print(a + b)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "8\n"
- ]
- }
- ],
- "source": [
- "myAdd(3,5) #Nothing looks wrong here, right?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "8\n"
- ]
- },
- {
- "ename": "TypeError",
- "evalue": "unsupported operand type(s) for +: 'NoneType' and 'int'",
- "output_type": "error",
- "traceback": [
- "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)",
- "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mmyAdd\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmyAdd\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m5\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m5\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;31m#Oops\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[1;32m\u001b[0m in \u001b[0;36mmyAdd\u001b[1;34m(a, b)\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mmyAdd\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mb\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mb\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[1;31mTypeError\u001b[0m: unsupported operand type(s) for +: 'NoneType' and 'int'"
- ]
- }
- ],
- "source": [
- "myAdd(myAdd(3,5), 5) #Oops"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "With return, we don't have this problem:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def myAdd(a,b):\n",
- " return a + b"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "myAdd(myAdd(3,5),5)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\"Outputs\" are helpful results of functions that actually mean something - \"Prints\" are just visuals to help you out!\n",
- "\n",
- "In short, if your function doesn't return anything, there's probably a problem!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## If Statements"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Sometimes when writing a program we want Python to make choices for us depending on the input. If statements are usually used in a context with variables that change, for example functions. Let's look at the syntax with a simple function that tests if the input is 10 or not:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def isTen(number):\n",
- " \n",
- " if number == 10:\n",
- " \n",
- " return \"Yes!\"\n",
- " \n",
- " else:\n",
- " \n",
- " return \"No!\"\n",
- " \n",
- "print(isTen(10))\n",
- "print(isTen(5))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Some important things here - first off the indents again; if statements, like function definitions, need whitespace for Python to understand the code. Secondly, notice that when we construct the condition (number == 10), it's a double equals sign instead of a single. This is because the single equals is already used for setting variables. There are many conditionals we can use (for example: <, >, <=, >= are less than, greater than, less than or equal to, greater than or equal to) - make sure to check out the Python documentation [here](https://docs.python.org/3/) to see examples of more."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Not all questions are Yes or No - and Python has a way for us to deal with this - elif. For example, say we want to write a program that tells us if a number greater than 5 or less than or equal to 3:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def fiveOrThree(number):\n",
- " \n",
- " if number > 5:\n",
- " \n",
- " return \"This is a big number!\"\n",
- "\n",
- " elif number <= 3:\n",
- " \n",
- " return \"This is a small number!\"\n",
- " \n",
- " else:\n",
- " \n",
- " return \"I don't know how big this number is!\"\n",
- " \n",
- "print(fiveOrThree(2))\n",
- "print(fiveOrThree(5))\n",
- "print(fiveOrThree(6))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Another helpful conditional to use is in, usually used with lists:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "fruit\n",
- "vegetables\n",
- "unknown\n"
- ]
- }
- ],
- "source": [
- "fruits = [\"banana\", \"orange\", \"strawberry\"]\n",
- "vegetables = [\"carrot\", \"potato\", \"broccoli\"] # Note: not extensive lists of fruit or vegetables\n",
- "\n",
- "def fruitOrVeg(food):\n",
- " \n",
- " if food in fruits:\n",
- " \n",
- " return \"fruit\"\n",
- " \n",
- " if food in vegetables:\n",
- " \n",
- " return \"vegetables\"\n",
- " \n",
- " else:\n",
- " \n",
- " return \"unknown\"\n",
- " \n",
- "print(fruitOrVeg(\"banana\"))\n",
- "print(fruitOrVeg(\"carrot\"))\n",
- "print(fruitOrVeg(\"soup\"))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Loops"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "There are two types of loop we'll look at here - the for loop and the while loop. Loops are used to do something simple over and over again to stop us from doing it. For example, say (for some reason) we don't know if the numbers 0 through 10 are bigger than 5 or smaller than 3. Using our function from earlier we can do the following:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "for number in range(11): #range(11) gives us a list of the numbers 0-10\n",
- " \n",
- " print(fiveOrThree(number))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The for loop executes the indented code for every element in the list range(11)."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "While loops are slightly diffent - they check for a condition before executing the indented code. For example, a way of rewriting the code above would be:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "number = 0\n",
- "while number <= 10:\n",
- " print(fiveOrThree(number))\n",
- " number += 1 #Shorthand way of saying number = number + 1"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Finally with loops, sometimes we want to stop the loop prematurely to save time, or when we get what we want. Firstly, let's look at an example that finds the numbers from 2 to 20 that are not prime. A prime number is a number that's only divisible by itself or 1 - so any non-prime number will be divisible by a number from 2 to n. We just need to find what these are:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "4 is not prime\n",
- "6 is not prime\n",
- "8 is not prime\n",
- "9 is not prime\n",
- "10 is not prime\n",
- "12 is not prime\n",
- "14 is not prime\n",
- "15 is not prime\n",
- "16 is not prime\n",
- "18 is not prime\n"
- ]
- }
- ],
- "source": [
- "for number in range(2, 20):\n",
- " \n",
- " for x in range(2, number): #iterates from 2 to our number\n",
- " \n",
- " if number % x == 0: #this means our number is divisible f\n",
- " \n",
- " print(str(number) + \" is not prime\")\n",
- " break\n",
- "\n",
- "\n",
- " "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Can we do better than this? What if we want to find what the number's prime factors are? Here's some code that puts all we've learnt together:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "number = 12847\n",
- "primes = []\n",
- "test = 2\n",
- "\n",
- "while True: #Sets up a loops that never ends unless we break it:\n",
- " \n",
- " if number == 1: #This will be clear later\n",
- " \n",
- " print(\"Decomposition found!\")\n",
- " print(primes)\n",
- " break #Finishes program\n",
- " \n",
- " elif number % test == 0: #If the number is divisible by the test number\n",
- " \n",
- " primes.append(test) #Adds the prime factor to the primes list\n",
- " number /= test #Shorthand for number = number / test\n",
- " \n",
- " else: \n",
- " test += 1"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Let's look at this in more detail - we set up our number, an empty list for the primes, and the test number 2. We then set up an infinite while loop that will only end if we break it, then ask if the number has been fully decomposed into its factors. If this is the case, we print the decomposition and break out of the loop, ending the program. If this isn't the case, we check to see if our test number divides our number. If this happens, we add our test number to the list, and divide our number by the test number. If neither of these conditions are met, we just add 1 to the test number and try again. Eventually, the number will keep being divided by prime numbers and reach 1, at which point the program ends.\n",
- "\n",
- "At first glance this program may seem complicated, don't worry! Break it down into parts and see if you can understand each bit, then put it all together - once you've done that, try turning this into a function so we can input what \"number\" is.\n",
- "\n",
- "Similarly, if this program seems a bit wasteful - you're right! We could turn this into a function to generalise it more, or use better syntax in places to speed the program up. Programming is more of art than a science - there are many \"right answers\"!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Another Look At Methods"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We've already seen a method in the last guide, namely the append method. Let's talk about them a bit more to get comfortable with them, as we'll see them pop up everywhere.\n",
- "\n",
- "Strings in Python can act as lists - we can iterate over them using for loops, as well as perform some unique methods on them. For example, we can make a string into all upper case using the .upper() method:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "string = \"hello python!\"\n",
- "print(string.upper())"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Similarly, there are some methods for lists:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "myList = [\"Tom\",\"Andy\",\"Pete\",\"Josh\"]\n",
- "\n",
- "print(myList.index(\"Andy\")) #Gives us the index of Andy\n",
- "print(myList.pop()) #Gives us the last element and removes it\n",
- "print(myList) #Gives us the list back, with the last element popped out."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Dictionaries"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Dictionaries are our first real example of a data structure. They let us assign values to custom indexes:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "HiPy = {\"location\": \"Liverpool University\", \"startDate\": 2016, \"language\": \"Python\"}"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "To get our entries back out of the dictionary we index as if it were a list with custom indexes:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "HiPy[\"location\"]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Dictionaries can help us manage data more intuitively at the price of using more memory. For example, if we wanted to store the marks of three students, we could use a list of lists, which is hard to read: "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "marks = [[90,86,70],[60,70,65],[90,40,60]]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Or use a list of dictionaries:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "Adam = {\"maths\": 90, \"english\": 86, \"science\":70}\n",
- "Billy = {\"maths\": 60, \"english\": 70, \"science\":65}\n",
- "Chris = {\"maths\": 90, \"english\": 40, \"science\":60}\n",
- "\n",
- "students = [Adam, Billy, Chris]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now we can reference everything from the students list, or reference things directly from the students in a more intuitive way:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "print(Adam[\"maths\"])\n",
- "print(Billy[\"science\"])\n",
- "print(students[1][\"english\"])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Worked Example"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Let's take a look at a program that outputs the first n numbers of the fibonacci sequence:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "def fib(n):\n",
- " a = 1\n",
- " b = 1\n",
- " fibList = [1,1]\n",
- " \n",
- " while len(fibList) < n:\n",
- " b = a + b\n",
- " a = b - a #Shuffles the numbers around so we get the next pair\n",
- " fibList.append(b)\n",
- " \n",
- " return fibList\n",
- "\n",
- "print(fib(10))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "As with our prime example before, we set up our variables, then a while loop that checks to see if we've reached the nth fibonacci number yet. If it hasn't, we generate the next in the sequence and add it to the list. If it has, we return the list and finish the program. \n",
- "\n",
- "There are many ways of improving this program, including using indexing, or simultaneously declaring what a and b are in the while loop - however this code works well enough for now."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Mini Project"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "For a long time, the number one programming challenge for programmers hoping to work at big tech companies was the \"FizzBuzz\" challenge. It involves making a program that given a number, returns Fizz if divisible by 3, and Buzz if divisible by 5, and FizzBuzz if divisible by both. Can you:\n",
- "\n",
- "* Make a function that does this?\n",
- "* Set up a for loop that runs this function on the numbers 1-100?\n",
- "* Using the map funciton, do the same as above, but without using a for loop?"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.6"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/[BASICS] Numpy and Pandas/.ipynb_checkpoints/Numpy and Pandas-checkpoint.ipynb b/[BASICS] Numpy and Pandas/.ipynb_checkpoints/Numpy and Pandas-checkpoint.ipynb
deleted file mode 100644
index e3bae59..0000000
--- a/[BASICS] Numpy and Pandas/.ipynb_checkpoints/Numpy and Pandas-checkpoint.ipynb
+++ /dev/null
@@ -1,788 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- ""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Why Numpy and Pandas?"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "For a long time, Python programmers who worked with data had to use the core Python libraries for importing, organising and manipulating data. The modules Numpy and Pandas give us tools we can use to work with data quickly and efficiently in a nicer format. By the end of this guide you should feel comfortable with Numpy arrays and Pandas series and dataframes."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Introduction to Numpy"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Numpy is a module that lets us generate more efficient lists that have the option to be multi-dimensional (stacked inside each other). Before we look at what Numpy can do, we have to first import the module. As with matplotlib, we will be importing it under a different name for brevity. Here we use \"np\"."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Almost all of Numpy's functionality comes from it's multi-dimensional arrays, which mostly operate like Python lists, but use less memory, have better performance and have some other cool features under the hood. To initialise an array, we use the function np.array:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[1 2 3 4]\n"
- ]
- }
- ],
- "source": [
- "a = np.array([1,2,3,4])\n",
- "print(a)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "A very important note is that the \"np.array\" function's argument is a list - Python won't understand you if you give it something else! For example - the command..."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "ename": "ValueError",
- "evalue": "only 2 non-keyword arguments accepted",
- "output_type": "error",
- "traceback": [
- "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)",
- "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0maError\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marray\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m4\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[1;31mValueError\u001b[0m: only 2 non-keyword arguments accepted"
- ]
- }
- ],
- "source": [
- "aError = np.array(1,2,3,4)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "... give us an error because Python expects a list, not four numbers.\n",
- "\n",
- "We can also make two dimensional arrays like so (note the nested brackets):"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[1 2 3 4]\n",
- " [5 6 7 8]]\n"
- ]
- }
- ],
- "source": [
- "a = np.array([ [1,2,3,4] , [5,6,7,8] ])\n",
- "print(a)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Numpy also comes with some functions to generate arrays - for example the function linspace() gives us an array of numbers equally spread out between the arguements. For example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[ 0. 0.5 1. 1.5 2. 2.5 3. 3.5 4. 4.5 5. 5.5 6. 6.5\n",
- " 7. 7.5 8. 8.5 9. 9.5 10. ]\n"
- ]
- }
- ],
- "source": [
- "b = np.linspace(0,10,21)\n",
- "print(b)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Gives us an array of 21 elements equally spaced from 0 to 10 (because we include endpoints here we have to be careful about how many numbers we want!)."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Numpy, unlike Python lists, can have operations performed on them directly:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[ 0. 0.25 1. 2.25 4. 6.25 9. 12.25 16. 20.25\n",
- " 25. 30.25 36. 42.25 49. 56.25 64. 72.25 81. 90.25\n",
- " 100. ]\n"
- ]
- }
- ],
- "source": [
- "print(b**2)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can also use numpy arrays in the same way as Python lists for graphing (in fact this is recommended):"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "
"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "import matplotlib.pyplot as plt #We need to import our graphing library!\n",
- "\n",
- "plt.plot(b,b**2)\n",
- "\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Numpy arrays can also be indexed, sliced and iterated over in the same way as Python lists can:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "0.0\n"
- ]
- }
- ],
- "source": [
- "print(b[0])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[0. 0.5 1. 1.5 2. 2.5 3. 3.5 4. 4.5 5. ]\n"
- ]
- }
- ],
- "source": [
- "print(b[0:11])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "0.0 is an element of our array!\n",
- "0.5 is an element of our array!\n",
- "1.0 is an element of our array!\n",
- "1.5 is an element of our array!\n",
- "2.0 is an element of our array!\n",
- "2.5 is an element of our array!\n",
- "3.0 is an element of our array!\n",
- "3.5 is an element of our array!\n",
- "4.0 is an element of our array!\n",
- "4.5 is an element of our array!\n",
- "5.0 is an element of our array!\n",
- "5.5 is an element of our array!\n",
- "6.0 is an element of our array!\n",
- "6.5 is an element of our array!\n",
- "7.0 is an element of our array!\n",
- "7.5 is an element of our array!\n",
- "8.0 is an element of our array!\n",
- "8.5 is an element of our array!\n",
- "9.0 is an element of our array!\n",
- "9.5 is an element of our array!\n",
- "10.0 is an element of our array!\n"
- ]
- }
- ],
- "source": [
- "for element in b:\n",
- " print(str(element) + \" is an element of our array!\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Apart from direct operations on arrays - this may seem a little redundant. So why do we use Numpy arrays over Python lists? Well, most scientific libraries leverage numpy for better performance. Better performance and a smaller memory footprint might not sound impressive now but imagine if you would work on a dataset with billions of entries; then these things become very important!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Pandas"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Numpy is the backbone of most data focused Python libraries, because it provides a solid foundation to build upon. One of the most important of these libraries is Pandas, which we use to create series and dataframes, i.e tables.\n",
- "\n",
- "As always, we first need to import the library. With pandas we use the alias \"pd\" by convention:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "metadata": {},
- "outputs": [],
- "source": [
- "import pandas as pd"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": true
- },
- "source": [
- "Pandas' functionality is two Python objects - the series, and the dataframe. For making series, we can use the Series function (note: this is case sensitive!):"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "0 1\n",
- "1 1\n",
- "2 2\n",
- "3 3\n",
- "4 5\n",
- "5 8\n",
- "dtype: int64\n"
- ]
- }
- ],
- "source": [
- "c = pd.Series([1,1,2,3,5,8])\n",
- "print(c)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The numbers in the left column are our index - it can be helpful to change this, for example if our data is time based. To do this, we add another arguement to the series function:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 17,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Monday 1\n",
- "Tuesday 1\n",
- "Wednesday 2\n",
- "Thursday 3\n",
- "Friday 5\n",
- "Saturday 8\n",
- "dtype: int64\n"
- ]
- }
- ],
- "source": [
- "c = pd.Series([1,1,2,3,5,8], index=[\"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"])\n",
- "print(c)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Dataframes are just a collection of series. To make a dataframe, we have a few options, all using the DataFrame function (again notice the capitals!).\n",
- "\n",
- "We can pass a two dimensional numpy array as an arguement, along with column names (here we use the random sublibrary of numpy to give us a 6x4 array of random numbers):\n",
- "\n",
- "(Note: here np.random.randn(x,y) gives us an x by y numpy array with random entries)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 19,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- " A B C D\n",
- "0 -1.304458 0.128916 0.917312 -0.830153\n",
- "1 -2.312278 -0.631357 -0.524241 -1.663592\n",
- "2 -1.527491 -0.136707 -1.041927 -0.649112\n",
- "3 0.621613 0.384033 -0.529702 1.046160\n",
- "4 0.603338 -1.430888 -1.414519 0.308135\n",
- "5 1.281230 -0.966232 0.618242 1.862749\n"
- ]
- }
- ],
- "source": [
- "d = pd.DataFrame(np.random.randn(6,4), columns=['A','B','C','D'])\n",
- "print(d) #Note, if you are using jupyter notebook, just outputting d here instead of printing it will give you a nicer format."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Another way is to pass a dictionary as our arguement to the function - here we use the function \"pd.date_range\" to generate an array of dates, starting from 30/03/2017 and ending at 02/04/2017:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 20,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- " A B C\n",
- "0 1 hello 2017-03-30\n",
- "1 2 hello 2017-03-31\n",
- "2 3 hello 2017-04-01\n",
- "3 4 hello 2017-04-02\n"
- ]
- }
- ],
- "source": [
- "e = pd.DataFrame({'A': [1,2,3,4], 'B':\"hello\", 'C': pd.date_range('20170330', periods=4)})\n",
- "print(e)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Most of the time during data analysis, we will looking at tables that are much larger than just 4 or 5 rows. It can be helpful to know some commands to give us summary information about our data without bringing up the whole frame.\n",
- "\n",
- "The head and tail methods give us the first and last row(s) of the frame:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 21,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- " A B C D\n",
- "0 -1.304458 0.128916 0.917312 -0.830153\n",
- "1 -2.312278 -0.631357 -0.524241 -1.663592\n",
- "2 -1.527491 -0.136707 -1.041927 -0.649112\n"
- ]
- }
- ],
- "source": [
- "print(d.head(3)) #Looks at the first 3 rows of our \"d\" dataframe"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 22,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- " A B C\n",
- "3 4 hello 2017-04-02\n"
- ]
- }
- ],
- "source": [
- "print(e.tail(1)) #Looks at the last row of our \"e\" dataframe"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The describe method can give us some summary statistics of our data:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 23,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- " A B C D\n",
- "count 6.000000 6.000000 6.000000 6.000000\n",
- "mean -0.439675 -0.442039 -0.329139 0.012365\n",
- "std 1.456953 0.691383 0.918213 1.306626\n",
- "min -2.312278 -1.430888 -1.414519 -1.663592\n",
- "25% -1.471733 -0.882513 -0.913870 -0.784893\n",
- "50% -0.350560 -0.384032 -0.526971 -0.170488\n",
- "75% 0.617044 0.062510 0.332621 0.861654\n",
- "max 1.281230 0.384033 0.917312 1.862749\n"
- ]
- }
- ],
- "source": [
- "print(d.describe())"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Accessing columns and rows of a dataframe is similar to lists and arrays - for columns we index as normal:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 24,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "0 -1.304458\n",
- "1 -2.312278\n",
- "2 -1.527491\n",
- "3 0.621613\n",
- "4 0.603338\n",
- "5 1.281230\n",
- "Name: A, dtype: float64\n"
- ]
- }
- ],
- "source": [
- "print(d['A'])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "For rows, we need to use the loc method:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 25,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "A -1.304458\n",
- "B 0.128916\n",
- "C 0.917312\n",
- "D -0.830153\n",
- "Name: 0, dtype: float64\n"
- ]
- }
- ],
- "source": [
- "print(d.loc[0])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "And finally, to get induvidual values, we can use a double-index:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 26,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "-1.3044583932951868"
- ]
- },
- "execution_count": 26,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "d['A'][0]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Finally, we can filter our data using logical expressions, to access the row in our dataframe e where column A is equal to 3 we can use: "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 27,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- " A B C\n",
- "2 3 hello 2017-04-01\n"
- ]
- }
- ],
- "source": [
- "print(e[e['A'] == 3])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Worked Example"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": true
- },
- "source": [
- "We're going to take a closer look at the random.randn function to see how this data is distributed:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 28,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- " 0\n",
- "count 100000.000000\n",
- "mean -0.002194\n",
- "std 1.000691\n",
- "min -4.194139\n",
- "25% -0.673841\n",
- "50% 0.000094\n",
- "75% 0.671483\n",
- "max 4.440165\n"
- ]
- }
- ],
- "source": [
- "import numpy as np\n",
- "import pandas as pd\n",
- "\n",
- "myData = pd.DataFrame(np.random.randn(100000))\n",
- "\n",
- "print(myData.describe())"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "So our random data has a mean of about 0 and a standard deviation of around 1. This seems to be a standard normal distribution, and in fact that's true - the \"n\" of \"randn\" stands for normal. We can illustrate this using a graph:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 29,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "image/png": "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\n",
- "text/plain": [
- "
"
- ]
- },
- "metadata": {
- "needs_background": "light"
- },
- "output_type": "display_data"
- }
- ],
- "source": [
- "import matplotlib.pyplot as plt\n",
- "\n",
- "mySortedData = myData.sort_values(0) #sorts the data in ascending order\n",
- "x = np.linspace(-10, 10, 100000) #setting up a dummy array\n",
- "\n",
- "plt.plot(mySortedData,x)\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Here we can see the cumulative distribution function of the normal distribution!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Mini Project"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Below we have a dataframe of marks in a class - can you find out:\n",
- "\n",
- "* The average mark for English?\n",
- "* Each student's average mark? (DON'T do this manually!!!)\n",
- "* The subject which, on average, students scored the least marks in?\n",
- "* The subject which each induvidual student did worst in.\n",
- "* The student who got the most marks in the class overall"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 30,
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import pandas as pd\n",
- "\n",
- "subjects = [\"Maths\",\"English\",\"Science\",\"Geography\",\"History\",\"Languages\"]\n",
- "marks = pd.DataFrame({\"Alice\": [85, 86, 98, 94, 2, 39],\"Billy\": [55, 26, 69, 39, 47, 15],\"Cameron\": [80, 5, 28, 28, 44, 37],\"David\": [ 5, 22, 95, 71, 62, 6],\"Ellie\": [75, 93, 66, 18, 87, 60],\"Faye\": [72, 0, 63, 51, 65, 83],\"Garry\": [67, 92, 62, 35, 0, 79],\"Harriet\": [51, 17, 87, 31, 91, 99],\"Izzy\": [63, 37, 58, 26, 39, 51],\"James\": [17, 7, 88, 27, 6, 16],\"Katie\": [15, 77, 12, 54, 81, 0],\"Liam\": [25, 35, 80, 71, 71, 9],\"Mason\": [70, 78, 4, 19, 61, 77],\"Noah\": [78, 96, 86, 42, 73, 51],\"Olivia\": [75, 81, 23, 19, 76, 3],\"Patrick\": [43, 50, 87, 94, 33, 65],\"Quinn\": [72, 1, 80, 96, 76, 56],\"Ross\": [ 3, 25, 30, 49, 84, 7],\"Sam\": [67, 29, 91, 64, 11, 43],\"Terri\": [63, 36, 70, 73, 13, 25],\"Umar\": [70, 30, 47, 71, 25, 57],\"Veronica\": [88, 34, 29, 92, 82, 62],\"Will\": [89, 11, 14, 56, 78, 63]}, index=subjects)"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.6"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/[BASICS] Setting Up Python/HiPy.pub b/[BASICS] Setting Up Python/HiPy.pub
deleted file mode 100644
index 2aff363..0000000
Binary files a/[BASICS] Setting Up Python/HiPy.pub and /dev/null differ
diff --git a/[BASICS] Setting Up Python/Setting Up Python Intro Document.pdf b/[BASICS] Setting Up Python/Setting Up Python Intro Document.pdf
deleted file mode 100644
index 2c66c0c..0000000
Binary files a/[BASICS] Setting Up Python/Setting Up Python Intro Document.pdf and /dev/null differ
diff --git a/[STATISTICS] ANOVA (Analysis Of Variance)/.ipynb_checkpoints/ANOVA (Analysis Of Variance)-checkpoint.ipynb b/[STATISTICS] ANOVA (Analysis Of Variance)/.ipynb_checkpoints/ANOVA (Analysis Of Variance)-checkpoint.ipynb
deleted file mode 100644
index ecd0915..0000000
--- a/[STATISTICS] ANOVA (Analysis Of Variance)/.ipynb_checkpoints/ANOVA (Analysis Of Variance)-checkpoint.ipynb
+++ /dev/null
@@ -1,368 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- ""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "ANOVA (Analysis Of Variance) lets us test to see if a number of samples have the same mean. It's similar to the independent 2-sample t-test, but doesn't restrict us to just 2 samples. We will look at one-way and two-way ANOVA, and by the end of this guide you should be confident in using these statistical methods in your own work."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## One Way ANOVA"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "One way ANOVA can be used when we have data categorised by 1 variable - for example, take the following dataframe of the force applied to a drivers head during a crash in 3 different sizes of cars:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 60,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- " Compact Large Medium\n",
- "0 543 600 566\n",
- "1 555 530 520\n",
- "2 502 498 580\n",
- "3 534 460 498\n",
- "4 611 478 511\n",
- "5 622 560 560\n"
- ]
- }
- ],
- "source": [
- "import numpy as np\n",
- "import pandas as pd\n",
- "\n",
- "cars = pd.DataFrame({\"Compact\": [543, 555, 502, 534, 611, 622], \"Medium\": [566,520,580,498,511,560], \"Large\": [600,530,498,460,478,560]})\n",
- "\n",
- "print(cars)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "A simple preliminary technique is to plot the boxplots of the different sets using matplotlib:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 61,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "image/png": "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\n/wEs38uzkwSEuAAAAABJRU5ErkJggg==\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "import matplotlib.pyplot as plt\n",
- "\n",
- "plt.boxplot([cars[\"Compact\"], cars[\"Medium\"], cars[\"Large\"]])\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "It certainly looks like these is some kind of downward trend as the car gets larger - but we need a way of statistically testing if the means are different. ANOVA lets us do this, and works on the assumption that every data point is picked independently from normal distributions with the same variance. Of course - each group can have a different mean (otherwise our data would all be the same), but the variance has to be equal. In ANOVA, the null hypothesis is that all the means are equal, and the alternative hypothesis is they are not."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Scipy has a really nice and easy way to do this: the f_oneway() function:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 62,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "F_onewayResult(statistic=1.1973440463010667, pvalue=0.3292756379801583)\n"
- ]
- }
- ],
- "source": [
- "import scipy.stats as stats\n",
- "\n",
- "print(stats.f_oneway(cars[\"Compact\"], cars[\"Medium\"], cars[\"Large\"]))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Here we can see a pvalue of 0.32 gives us no evidence the means are different. If we want more detailed output, we can use the statsmodels library to get more control over what's happening. For this we need to edit our dataframe a little. The melt method for pandas lets us do this really easily:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 63,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- " Type Force\n",
- "0 Compact 543\n",
- "1 Compact 555\n",
- "2 Compact 502\n",
- "3 Compact 534\n",
- "4 Compact 611\n",
- "5 Compact 622\n",
- "6 Large 600\n",
- "7 Large 530\n",
- "8 Large 498\n",
- "9 Large 460\n",
- "10 Large 478\n",
- "11 Large 560\n",
- "12 Medium 566\n",
- "13 Medium 520\n",
- "14 Medium 580\n",
- "15 Medium 498\n",
- "16 Medium 511\n",
- "17 Medium 560\n"
- ]
- }
- ],
- "source": [
- "cars2 = pd.melt(cars, var_name=\"Type\", value_name=\"Force\")\n",
- "print(cars2)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now we can use the statsmodels libary to build a model and then perform the analysis:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 92,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- " sum_sq df F PR(>F)\n",
- "C(Type) 4854.777778 2.0 1.197344 0.329276\n",
- "Residual 30409.666667 15.0 NaN NaN\n"
- ]
- }
- ],
- "source": [
- "import statsmodels.api as sm\n",
- "from statsmodels.formula.api import ols\n",
- "\n",
- "#Fits the data to a model using the formula \"Force ~ C(Type)\" - since Type is categorical we need the C()\n",
- "model = ols('Force ~ C(Type)', data=cars2).fit() \n",
- " \n",
- "anova_table = sm.stats.anova_lm(model, typ=2) #Performs Analysis on this model\n",
- "print(anova_table)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Here we can see the test statistic (1.197) and our p-value again (0.329) as well as the sum of squares data. This method doesn't seem useful now, but will be useful when we look at the next section."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Two Way ANOVA"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Two way ANOVA is similar to one way ANOVA in that we're testing data split catagorically for equal means. However this time, our data is sorted into two different types of categories, and what we're testing for is slightly different. The assumptions here are the same as one-way ANOVA, but the groups also must be the same size. We are also testing three null hypothesis at once:\n",
- "\n",
- "* The Population Means of the first factor are equal (One-way ANOVA on the first type of category)\n",
- "* The Population Means of the second factor are equal (One-way ANOVA on the second type of category)\n",
- "* There is no interaction between the two factors."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Here we are looking at the length of odontoblasts (cells responsible for tooth growth) in 60 guinea pigs. As this dataset is too large to copy out, we're going to import it. You can download the datafile from the same folder this notebook is in [here](https://www.google.co.uk)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 101,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- " len supp dose\n",
- "0 4.2 VC 0.5\n",
- "1 11.5 VC 0.5\n",
- "2 7.3 VC 0.5\n",
- "3 5.8 VC 0.5\n",
- "4 6.4 VC 0.5\n"
- ]
- }
- ],
- "source": [
- "teeth = pd.read_csv(\"ToothGrowth.csv\")\n",
- "print(teeth.head())"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The data is split into three columns: our dependent variable - the length of odontoblasts, the form of the suppliment given (OJ is orange juice, VC is ascorbic acid), and the dose of vitamin C they were given. Statsmodels lets us perform a two-way ANOVA test using a similar method to above:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 99,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- " sum_sq df F PR(>F)\n",
- "C(supp) 205.350000 1.0 15.571979 2.311828e-04\n",
- "C(dose) 2426.434333 2.0 91.999965 4.046291e-18\n",
- "C(supp):C(dose) 108.319000 2.0 4.106991 2.186027e-02\n",
- "Residual 712.106000 54.0 NaN NaN\n"
- ]
- }
- ],
- "source": [
- "import statsmodels.api as sm\n",
- "from statsmodels.formula.api import ols\n",
- " \n",
- "model = ols('len ~ C(supp) + C(dose) + C(supp)*C(dose)', data=teeth).fit() #Formula for Two-way ANOVA is C(1) + C(2) + C(1)*C(2)\n",
- " \n",
- "anova_table = sm.stats.anova_lm(model, typ=2) #Performs Analysis on this model\n",
- "print(anova_table)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The first line gives us a p-value of 2.3e-04, which gives us strong evidence that the means are not equal when categorised by suppliment (i.e, orange juice gives different results than ascorbic acid).\n",
- "\n",
- "The second line gives us a p-value of 4.04e-18, which again gives us strong evidence that the means are not equal when categorised by dose (i.e, different doses give us different growths).\n",
- "\n",
- "The third line give us a p-value of 0.02186, which gives us evidence that the two categorical factors are related in some way."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Mini Project"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Here we have some data detailing the anger scores categorised by gender, and whether or not they are athletes. You can download the datafile from the same folder this notebook is in [here](https://www.google.co.uk). The \"AngerOut\" score is a measurement of verbally or phyiscally expressing anger."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 107,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- " Gender Sports AngerOut\n",
- "0 female athlete 18\n",
- "1 female athlete 14\n",
- "2 female athlete 13\n",
- "3 female athlete 17\n",
- "4 male athlete 16\n"
- ]
- }
- ],
- "source": [
- "angry = pd.read_csv(\"angry_moods.csv\")\n",
- "print(angry.head())"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Can you perform analysis on the data set and conclude if:\n",
- "\n",
- "* Men and Women express their anger to a similar degree.\n",
- "* Athletes and Non-athletes express their anger to a similar degree.\n",
- "* There is any relationship between whether or not someone is an athelete, their gender, and if they express their anger phyisically or verbally."
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.5.2"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/[STATISTICS] Hypothesis Testing In Python/.ipynb_checkpoints/Hypothesis Testing In Python-checkpoint.ipynb b/[STATISTICS] Hypothesis Testing In Python/.ipynb_checkpoints/Hypothesis Testing In Python-checkpoint.ipynb
deleted file mode 100644
index f88bb15..0000000
--- a/[STATISTICS] Hypothesis Testing In Python/.ipynb_checkpoints/Hypothesis Testing In Python-checkpoint.ipynb
+++ /dev/null
@@ -1,388 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- ""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Hypothesis testing is the most basic form of analyical statistics. It works by us giving a null hypothesis, say, the mean of a population being equal to 50, then using samples from the same population we can test whether our null hypothesis is true or not. Hypothesis testing is easy to do with Python using the scipy library - and the statsmodels library can give us some additional functionality when needed. By the end of this guide you should be comfortable using Python to perform simple hypothesis test and be able to apply it to real world problems."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Student's T-Test"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Student's T-Test can tell us if two means are equal, or if a mean is equal to a particular value. Below we have the data for IQ scores for 50 people, and we want to test, using the sample, if the mean of the general population is equal to 100."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "scores = [117,137,105,120,44,94,89,61,92,123,130,119,79,119,95,95,108,92,110,121,85,65,84,100,83,74,80,127,106,88,145,86,123,107,91,77,72,138,92,50,102,96,109,97,141,82,94,115,101,91]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "For a preliminary look at our data, we can quickly graph it as a histogram using matplotlib:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "image/png": "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\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "import matplotlib.pyplot as plt\n",
- "\n",
- "plt.hist(scores)\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "The student t-test assumes our data is normally distributed - meaning the data has a bell shape to it. While we can see our data above isn't perfect, it's good enough to continue.\n",
- "\n",
- "We want to test if the mean IQ of the population is 100 using this sample. The function we want is ttest_1samp() in the scipy.stats module. Let's run this and see what we get:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Ttest_1sampResult(statistic=-0.30763272152834936, pvalue=0.75966563634430628)\n"
- ]
- }
- ],
- "source": [
- "import scipy.stats as stats #can also be written as \"from scipy import stats\"\n",
- "\n",
- "print(stats.ttest_1samp(scores,100))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "What does this output mean? The statistic is a helpful number to have because it's the number we compare to the distribution (in this case, the t-49 distribution) to make our conclusions. The pvalue is what we're interested in. It's the probability that given the null hypothesis (the mean being 100), our sample gives us the result it does. How do we convert this to a definitive yes/no result? We need to use significance levels. Significance levels are thresholds at which we reject or accept our null hypothesis depending on the p-value. If the p-value is above our significance level, we cannot reject our null hypothesis - but if it is lower, we can. Typically we use a significance value of 5%, but larger or smaller significance levels can be used. Remember - the smaller the significane level, the stronger evidence we have to reject our null hypothesis if the p-value is lower than it.\n",
- "\n",
- "In our case, a p-value of 75.9% is well above 5%, so there is no reason to reject our null hypothesis of the population mean being equal to 100.\n",
- "\n",
- "To show you what happens when the null hypothesis is false, let's look at what happens when we test for the null hypothesis being equal to 150:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Ttest_1sampResult(statistic=-16.003179738280803, pvalue=4.2848532726844928e-21)\n"
- ]
- }
- ],
- "source": [
- "print(stats.ttest_1samp(scores,150))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Our p-value is now 4.28 e-21 - that's very, very small. In other words, there is very strong evidence (p-value < 1%) that the population mean for IQ is not 150, as we'd expect."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": true
- },
- "source": [
- "We've looked at a one-sample t-test, testing if one sample is equal to a mean we choose ourselves - but what if we want to test if two samples are equal? For this we need to use an independent 2-sample t-test. This test assumes the variances of the two sets are roughly equal - we can test this later. Below we have the same data, but split into genders:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 23,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[117, 137, 105, 120, 44, 94, 89, 61, 92, 123, 130, 119, 79, 119, 95, 95, 108, 92, 110, 121, 85, 65]\n",
- "[84, 100, 83, 74, 80, 127, 106, 88, 145, 86, 123, 107, 91, 77, 72, 138, 92, 50, 102, 96, 109, 97, 141, 82, 94, 115, 101, 91]\n"
- ]
- }
- ],
- "source": [
- "scores = [117,137,105,120,44,94,89,61,92,123,130,119,79,119,95,95,108,92,110,121,85,65,84,100,83,74,80,127,106,88,145,86,123,107,91,77,72,138,92,50,102,96,109,97,141,82,94,115,101,91]\n",
- "men = scores[:22] #The data was sorted so the first 21 entries were men.\n",
- "women = scores[22:] #So from the 22nd onwards we have the women.\n",
- "print(men)\n",
- "print(women)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Testing if the means are equal is easy, using the ttest_ind() function. Here the null hypothesis is that the two means are equal."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 24,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Ttest_indResult(statistic=0.27009541129591547, pvalue=0.78824475119470483)\n"
- ]
- }
- ],
- "source": [
- "print(stats.ttest_ind(men,women))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Again, we have a p-value of 79%, meaning there is no evidence to reject the null hypothesis. Therefore from this test we can conclude that men and women have the same average IQ."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "There's a special case of two sampled t-test where the data is paired - for example, if we give 25 people a drug and measure their heart rate before and 15mins after taking the drug, we have 25 data points for each sample. For each data point in the control set we have a corresponding data point in the other set from the same person, so our data is paired. We also don't need for both sets of data to be normally distributed - it's enough for just the difference to be. If these condition are met, we can use a more powerful version of the independent 2 sample t-test; the 2 sample paired t-test. Below we have the data for the experiment above:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 36,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "control = [70, 80, 86, 92, 84, 69, 73, 101, 78, 72, 74, 83, 80, 73, 84, 85, 80, 85, 74, 84, 79, 83, 86, 76, 77]\n",
- "fifteen = [89, 99, 105, 111, 103, 87, 92, 119, 96, 91, 93, 102, 98, 92, 103, 104, 98, 104, 92, 103, 97, 102, 105, 95, 96]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "For this situation we use the ttest_rel() function - the null hypothesis here is that the means are equal:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 37,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "Ttest_relResult(statistic=-204.25194526088882, pvalue=2.1036620058407739e-40)"
- ]
- },
- "execution_count": 37,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "stats.ttest_rel(control,fifteen)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Our p-value is 2.1 e-40, which strongly suggests that the means are not equal.\n",
- "\n",
- "The paired t-test is more powerful than the independent t-test, meaning that it will pick up on smaller differences between the two means."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Testing For Equal Variance"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "If we have two samples we want to test for equal variance, either for a direct test or to check we are okay to use one of the tests above, we have a couple of options:\n",
- "\n",
- "* F-test (extremely dependent on normality, which isn't very helpful for us)\n",
- "* Bartlett's Test\n",
- "* Levene's Test (better than Barlett's test for data which is not normally distributed)\n",
- "\n",
- "Scipy has functions for Bartlett's Test and Levene's test, which are bartlett() and levene respectively. For both of these, the null hypothesis is that the variances are equal. Let's test to see if the variances are equal for our IQs split by gender is the same:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 39,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "BartlettResult(statistic=0.11379496878318175, pvalue=0.73586430378344914)\n",
- "LeveneResult(statistic=0.37710466803928877, pvalue=0.54205660176957238)\n"
- ]
- }
- ],
- "source": [
- "print(stats.bartlett(men,women))\n",
- "print(stats.levene(men,women))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Both tests show us that there is no reason to assume the variances aren't equal. The tests we did earlier are valid!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Testing For Normality"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Some of our tests require that our data is normally distributed. For this we can use D’Agostino and Pearson's test by using the normaltest() function. Let's test if our IQs were normally distributed:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 43,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "NormaltestResult(statistic=0.10212051194763901, pvalue=0.95022141229082702)\n"
- ]
- }
- ],
- "source": [
- "print(stats.normaltest(scores))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Looks like they are! Most tests are robust against non-normality, meaning that even if the data isn't normally distributed, the test will still work - however, it's always worth testing to see how worried we should be - if our p-value came back below 0.01, it might be a good idea to use a different, non-parametric test."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Mini Project"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Below we have two runners, Angela and Bill, and 50 training times for an upcoming race. Using statistical tests, test to see if;\n",
- "\n",
- "* The two means are the same.\n",
- "* The two variances are the same.\n",
- "* The data is normally distributed."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 58,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "angela = [141, 151, 151, 154, 150, 143, 153, 149, 156, 144, 158, 147, 145, 149, 159, 154, 150, 154, 145, 151, 160, 151, 149, 158, 139, 165, 149, 157, 153, 154, 144, 148, 147, 153, 144, 151, 143, 153, 151, 142, 144, 147, 142, 149, 147, 154, 150, 138, 150, 148]\n",
- "bill = [103, 109, 93, 95, 107, 96, 102, 99, 105, 101, 99, 107, 102, 95, 98, 112, 95, 110, 103, 107, 100, 95, 92, 101, 103, 95, 97, 102, 99, 108, 98, 100, 100, 97, 101, 92, 101, 108, 102, 93, 101, 99, 105, 100, 101, 100, 92, 92, 92, 90]"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.5.2"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
-}
diff --git a/__pycache__/fizzbuzz.cpython-35.pyc b/__pycache__/fizzbuzz.cpython-35.pyc
deleted file mode 100644
index 6476114..0000000
Binary files a/__pycache__/fizzbuzz.cpython-35.pyc and /dev/null differ
diff --git a/docs/CNAME b/docs/CNAME
deleted file mode 100644
index e8de1ff..0000000
--- a/docs/CNAME
+++ /dev/null
@@ -1 +0,0 @@
-www.hipy.uk
\ No newline at end of file
diff --git a/docs/contact.html b/docs/contact.html
deleted file mode 100644
index 9d29dea..0000000
--- a/docs/contact.html
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
Contact
-
Got a question? Complete the form below. We'll get back to you.
\ No newline at end of file
diff --git a/docs/how.html b/docs/how.html
deleted file mode 100644
index f8e05ad..0000000
--- a/docs/how.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-- What?
-
We deliver bespoke coding workshops
-
Highly interactive sessions taylored to the needs of your cohort.
-
- We are experts at providing introductory training sessions for the
- Python coding language. Our workshops rely heavily on a learn by doing approach to coding.
-
-
All students who attend our workshops join our cdtPy network and receive support from us throughout their doctoral training.
\ No newline at end of file
diff --git a/docs/programme.html b/docs/programme.html
deleted file mode 100644
index 1687bf0..0000000
--- a/docs/programme.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-- Why?
-
Writing your thesis is tough.
-
Sometimes it's hard to get motivated. That's where we come in.
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas semper enim a eros accumsan, vulputate imperdiet turpis blandit. Suspendisse sed purus nec elit elementum tempus.
-
-
-
\ No newline at end of file
diff --git a/docs/register.html b/docs/register.html
deleted file mode 100644
index 93dc203..0000000
--- a/docs/register.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ullamcorper egestas ullamcorper. Aenean facilisis varius augue, sed consequat neque fringilla ut. Cras at est eu lectus pulvinar dapibus eu quis dolor. Vivamus mattis odio et enim malesuada luctus. Pellentesque libero quam, porta vel porta id, vulputate in sem. Ut consequat bibendum leo, quis condimentum arcu lobortis in. Proin metus leo, porta vel ipsum imperdiet, elementum pharetra sapien. Phasellus dapibus commodo semper.
-
-
-
13:15
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ullamcorper egestas ullamcorper.
-
-
-
-
Task name
-
-
Task name
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/what.html b/docs/what.html
deleted file mode 100644
index 74ce082..0000000
--- a/docs/what.html
+++ /dev/null
@@ -1,147 +0,0 @@
-
-
\n */\n /* global -ngRouteModule */\nvar ngRouteModule = angular.module('ngRoute', ['ng']).\n provider('$route', $RouteProvider),\n $routeMinErr = angular.$$minErr('ngRoute');\n\n/**\n * @ngdoc provider\n * @name $routeProvider\n *\n * @description\n *\n * Used for configuring routes.\n *\n * ## Example\n * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.\n *\n * ## Dependencies\n * Requires the {@link ngRoute `ngRoute`} module to be installed.\n */\nfunction $RouteProvider() {\n function inherit(parent, extra) {\n return angular.extend(Object.create(parent), extra);\n }\n\n var routes = {};\n\n /**\n * @ngdoc method\n * @name $routeProvider#when\n *\n * @param {string} path Route path (matched against `$location.path`). If `$location.path`\n * contains redundant trailing slash or is missing one, the route will still match and the\n * `$location.path` will be updated to add or drop the trailing slash to exactly match the\n * route definition.\n *\n * * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up\n * to the next slash are matched and stored in `$routeParams` under the given `name`\n * when the route matches.\n * * `path` can contain named groups starting with a colon and ending with a star:\n * e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name`\n * when the route matches.\n * * `path` can contain optional named groups with a question mark: e.g.`:name?`.\n *\n * For example, routes like `/color/:color/largecode/:largecode*\\/edit` will match\n * `/color/brown/largecode/code/with/slashes/edit` and extract:\n *\n * * `color: brown`\n * * `largecode: code/with/slashes`.\n *\n *\n * @param {Object} route Mapping information to be assigned to `$route.current` on route\n * match.\n *\n * Object properties:\n *\n * - `controller` – `{(string|function()=}` – Controller fn that should be associated with\n * newly created scope or the name of a {@link angular.Module#controller registered\n * controller} if passed as a string.\n * - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be\n * published to scope under the `controllerAs` name.\n * - `template` – `{string=|function()=}` – html template as a string or a function that\n * returns an html template as a string which should be used by {@link\n * ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.\n * This property takes precedence over `templateUrl`.\n *\n * If `template` is a function, it will be called with the following parameters:\n *\n * - `{Array.