{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Module 4\n", "\n", "## Video 21: My Code isn't Working!\n", "**Python for the Energy Industry**\n", "\n", "In this lesson, we will start by looking at some common errors in Python. We shall then look at technqiues for identifying errors, and discuss where to go for more information about an error." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Common Mistakes\n", "\n", "### Versions\n", "\n", "Two versions of Python in active use, Python 2.7.x and Python 3.6.x, are broadly very similar but do have some differences which mean that code meant to run on Python 2 won't work on 3 and vice versa. A very common example of this is with print:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "# Uncomment and run the following line\n", "#print \"hello\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This statement will work in Python 2 but not in Python 3.\n", "\n", "### Indentation\n", "\n", "Python recognises 4 spaces (also produced by a tab) as an indent. If your indentation is not consistent, e.g. using 5 spaces instead of 4, python will give an IndentationError." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "# Uncomment and run the following block\n", "\n", "#for i in range(4):\n", "# print(i)\n", "# for j in range(3):\n", "# print(i*j)\n", "# \n", "# print('done')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Loops\n", "\n", "Remember that a loops do not include the last item specified in range. Forgetting this can lead to errors like this:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "my_nums = []\n", "for i in range(0,10):\n", " my_nums.append(i)\n", " \n", "# Uncomment and run the following line \n", "#print(my_nums[10])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Scope\n", "\n", "Scope is a tricky concept in Python, which relates to how variables are treated by different parts of your code. Scope is particularly relevant to functions that you have defined. Consider the following two examples:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "52\n" ] } ], "source": [ "a = 3\n", "def f(x):\n", " y = x**2 + a\n", " print(y)\n", " \n", "f(7)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "49\n" ] } ], "source": [ "def f(x):\n", " y = x**2\n", " print(y)\n", " \n", "f(7)\n", "# Uncomment and run the following line\n", "# print(y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the first example, we create a variable `a` outside of the function and then access it inside the function. This works fine. However, when we create a variable `y` inside the function and try to access it outside the function, we get an error. This is because `y` is 'local' to the function `f`, whereas `a`, which is not inside a function, is 'global'. Here's another example of how scope can lead to confusion:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "54\n", "3\n" ] } ], "source": [ "a = 3\n", "def f(x):\n", " a = 5\n", " y = x**2 + a\n", " print(y)\n", " \n", "f(7)\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Inside the function, we change the value of `a`, and this is reflected in our calculation of y. But outside the function, when we access `a`, it still has its original value. This is because `a` inside the function is a copy of the original. \n", "\n", "Scope is confusing! Even for more experienced programmers. So don't worry if it doesn't fully make sense, but be aware that it could be causing errors." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Copying Lists\n", "\n", "Note the following:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[3, 5, 7, 9]\n", "[3, 11, 7, 9]\n" ] } ], "source": [ "a = [3,5,7,9]\n", "b = a\n", "print(b)\n", "a[1] = 11\n", "print(b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Why did `b` change, even though we only modified `a`? Because here, `b=a` actually makes `a` and `b` point to the same list. It's not making a new copy. If you want `a` and `b` to be unique copies of the same list, do this:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[3, 5, 7, 9]\n", "[3, 5, 7, 9]\n" ] } ], "source": [ "a = [3,5,7,9]\n", "b = a.copy()\n", "print(b)\n", "a[1] = 11\n", "print(b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*Note: this applies not just to lists, but dictionaries, numpy arrays, and pandas dataframes too! In all cases, .copy() will make you a unique copy.*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Finding Bugs\n", "\n", "Often, the simplest way of finding problems in your code is simply to use `print` statements to see what is happening to variables at different points in your code. A more advanced approach is to use the built-in debugger: https://ipython.readthedocs.io/en/stable/interactive/magics.html#magic-debug" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Getting More Info\n", "\n", "If you don't understand why you are getting an error, it's good to look it up online. If you google the error message, you may find e.g. Stack Overflow pages with a solution. Issues specific to using functions from numpy, pandas, or other modules can often be found by looking up the relevant documentation pages:\n", "- https://numpy.org/doc/1.19/reference/index.html\n", "- https://pandas.pydata.org/docs/user_guide/index.html" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "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.7.9" } }, "nbformat": 4, "nbformat_minor": 4 }