diff --git a/.ipynb_checkpoints/not_so_obvious_python_stuff-checkpoint.ipynb b/.ipynb_checkpoints/not_so_obvious_python_stuff-checkpoint.ipynb
index de36159..3678a4e 100644
--- a/.ipynb_checkpoints/not_so_obvious_python_stuff-checkpoint.ipynb
+++ b/.ipynb_checkpoints/not_so_obvious_python_stuff-checkpoint.ipynb
@@ -1,7 +1,7 @@
{
"metadata": {
"name": "",
- "signature": "sha256:a9475a6f1134f87066829ecff7dab70b1fab2b2cc8ae3ee110b3e719b9626c23"
+ "signature": "sha256:2e4322ee7bffc6746194af4b3ac6bb9cd8794c14bea2575e3097821a7d5f9b52"
},
"nbformat": 3,
"nbformat_minor": 0,
@@ -63,7 +63,11 @@
"- [Python's LEGB scope resolution and the keywords `global` and `nonlocal`](#python_legb)\n",
"- [When mutable contents of immutable tuples aren't so mutable](#immutable_tuple)\n",
"- [List comprehensions are fast, but generators are faster!?](#list_generator)\n",
- "- [Public vs. private class methods and name mangling](#private_class)"
+ "- [Public vs. private class methods and name mangling](#private_class)\n",
+ "- [The consequences of modifying a list when looping through it](#looping_pitfall)\n",
+ "- [Dynamic binding and typos in variable names](#dynamic_binding)\n",
+ "- [List slicing using indexes that are \"out of range](#out_of_range_slicing)\n",
+ "- [Reusing global variable names and UnboundLocalErrors](#unboundlocalerror)"
]
},
{
@@ -515,7 +519,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Don't use mutable objects (e.g., dictionaries, lists, sets, etc.) as default arguments for functions! You might expect that a new list is created every time when we call the function without providing an argument for the default parameter, but this is not the case: Python will create the mutable object (default parameter) the first time the function is defined - not when it is called, see the following code:\n",
+ "Don't use mutable objects (e.g., dictionaries, lists, sets, etc.) as default arguments for functions! You might expect that a new list is created every time when we call the function without providing an argument for the default parameter, but this is not the case: **Python will create the mutable object (default parameter) the first time the function is defined - not when it is called**, see the following code:\n",
"\n",
"(Original source: [http://docs.python-guide.org/en/latest/writing/gotchas/](http://docs.python-guide.org/en/latest/writing/gotchas/)"
]
@@ -548,6 +552,48 @@
],
"prompt_number": 1
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Another good example showing that demonstrates that default arguments are created when the function is created (**and not when it is called!**):"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "import time\n",
+ "def report_arg(my_default=time.time()):\n",
+ " print(my_default)\n",
+ "\n",
+ "report_arg()\n",
+ "\n",
+ "time.sleep(5)\n",
+ "\n",
+ "report_arg()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "1397764090.456688\n",
+ "1397764090.456688"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "\n"
+ ]
+ }
+ ],
+ "prompt_number": 10
+ },
{
"cell_type": "markdown",
"metadata": {},
@@ -1299,6 +1345,358 @@
],
"prompt_number": 28
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "
\n",
+ "
\n",
+ "\n",
+ "## The consequences of modifying a list when looping through it"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "It can be really dangerous to modify a list when iterating through - it is a very common pitfall that can cause unintended behavior! \n",
+ "Look at the following examples, and for a fun exercise: try to figure out what is going on before you skip to the solution!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "a = [1, 2, 3, 4, 5]\n",
+ "for i in a:\n",
+ " if not i % 2:\n",
+ " a.remove(i)\n",
+ "print(a)"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "[1, 3, 5]\n"
+ ]
+ }
+ ],
+ "prompt_number": 3
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "b = [2, 4, 5, 6]\n",
+ "for i in b:\n",
+ " if not i % 2:\n",
+ " b.remove(i)\n",
+ "print(b)"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "[4, 5]\n"
+ ]
+ }
+ ],
+ "prompt_number": 4
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "
\n",
+ "
\n",
+ "**The solution** is that we are iterating through the list index by index, and if we remove one of the items in-between, we inevitably mess around with the indexing, look at the following example, and it will become clear:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "b = [2, 4, 5, 6]\n",
+ "for index, item in enumerate(b):\n",
+ " print(index, item)\n",
+ " if not item % 2:\n",
+ " b.remove(item)\n",
+ "print(b)"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "0 2\n",
+ "1 5\n",
+ "2 6\n",
+ "[4, 5]\n"
+ ]
+ }
+ ],
+ "prompt_number": 7
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "
\n",
+ "
\n",
+ "\n",
+ "## Dynamic binding and typos in variable names\n",
+ "Be careful, dynamic binding is convenient, but can also quickly become dangerous!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "print('first list:')\n",
+ "for i in range(3):\n",
+ " print(i)\n",
+ " \n",
+ "print('\\nsecond list:')\n",
+ "for j in range(3):\n",
+ " print(i) # I (intentionally) made typo here!"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "first list:\n",
+ "0\n",
+ "1\n",
+ "2\n",
+ "\n",
+ "second list:\n",
+ "2\n",
+ "2\n",
+ "2\n"
+ ]
+ }
+ ],
+ "prompt_number": 14
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "
\n",
+ "
\n",
+ "\n",
+ "## List slicing using indexes that are \"out of range\""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "As we have all encountered it 1 (x10000) time(s) in our live, the infamous `IndexError`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "my_list = [1, 2, 3, 4, 5]\n",
+ "print(my_list[5])"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "IndexError",
+ "evalue": "list index out of range",
+ "output_type": "pyerr",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\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[0mmy_list\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m3\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m4\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m5\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmy_list\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;31mIndexError\u001b[0m: list index out of range"
+ ]
+ }
+ ],
+ "prompt_number": 15
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "But suprisingly, it is not raised when we are doing list slicing, which can be a really pain for debugging:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "my_list = [1, 2, 3, 4, 5]\n",
+ "print(my_list[5:])"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "[]\n"
+ ]
+ }
+ ],
+ "prompt_number": 16
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "
\n",
+ "
\n",
+ "\n",
+ "## Reusing global variable names and `UnboundLocalErrors`"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Usually, it is no problem to access global variables in the local scope of a function:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "def my_func():\n",
+ " print(var)\n",
+ "\n",
+ "var = 'global'\n",
+ "my_func()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "global\n"
+ ]
+ }
+ ],
+ "prompt_number": 37
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "And is also no problem to use the same variable name in the local scope without affecting the local counterpart: "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "def my_func():\n",
+ " var = 'locally changed'\n",
+ "\n",
+ "var = 'global'\n",
+ "my_func()\n",
+ "print(var)"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "global\n"
+ ]
+ }
+ ],
+ "prompt_number": 38
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "But we have to be careful if we use a variable name that occurs in the global scope, and we want to access it in the local function scope if we want to reuse this name:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "def my_func():\n",
+ " print(var) # want to access global variable\n",
+ " var = 'locally changed' # but Python thinks we forgot to define the local variable!\n",
+ " \n",
+ "var = 'global'\n",
+ "my_func()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "UnboundLocalError",
+ "evalue": "local variable 'var' referenced before assignment",
+ "output_type": "pyerr",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mUnboundLocalError\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 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mvar\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'global'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0mmy_func\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;36mmy_func\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmy_func\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----> 2\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvar\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# want to access global variable\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0mvar\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'locally changed'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mvar\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'global'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;31mUnboundLocalError\u001b[0m: local variable 'var' referenced before assignment"
+ ]
+ }
+ ],
+ "prompt_number": 40
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "In this case, we have to use the `global` keyword!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "def my_func():\n",
+ " global var\n",
+ " print(var) # want to access global variable\n",
+ " var = 'locally changed' # changes the gobal variable\n",
+ "\n",
+ "var = 'global'\n",
+ "\n",
+ "my_func()\n",
+ "print(var)"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "global\n",
+ "locally changed\n"
+ ]
+ }
+ ],
+ "prompt_number": 43
+ },
{
"cell_type": "code",
"collapsed": false,
diff --git a/not_so_obvious_python_stuff.ipynb b/not_so_obvious_python_stuff.ipynb
index 03255fd..3678a4e 100644
--- a/not_so_obvious_python_stuff.ipynb
+++ b/not_so_obvious_python_stuff.ipynb
@@ -1,7 +1,7 @@
{
"metadata": {
"name": "",
- "signature": "sha256:02c6c63beb1de9373d69615a4ba37640a7b01c8f2d088dbfaa84bdaf3452f1c5"
+ "signature": "sha256:2e4322ee7bffc6746194af4b3ac6bb9cd8794c14bea2575e3097821a7d5f9b52"
},
"nbformat": 3,
"nbformat_minor": 0,
@@ -64,7 +64,10 @@
"- [When mutable contents of immutable tuples aren't so mutable](#immutable_tuple)\n",
"- [List comprehensions are fast, but generators are faster!?](#list_generator)\n",
"- [Public vs. private class methods and name mangling](#private_class)\n",
- "- [The consequences of modifying a list when looping through it](#looping_pitfall)"
+ "- [The consequences of modifying a list when looping through it](#looping_pitfall)\n",
+ "- [Dynamic binding and typos in variable names](#dynamic_binding)\n",
+ "- [List slicing using indexes that are \"out of range](#out_of_range_slicing)\n",
+ "- [Reusing global variable names and UnboundLocalErrors](#unboundlocalerror)"
]
},
{
@@ -516,7 +519,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "Don't use mutable objects (e.g., dictionaries, lists, sets, etc.) as default arguments for functions! You might expect that a new list is created every time when we call the function without providing an argument for the default parameter, but this is not the case: Python will create the mutable object (default parameter) the first time the function is defined - not when it is called, see the following code:\n",
+ "Don't use mutable objects (e.g., dictionaries, lists, sets, etc.) as default arguments for functions! You might expect that a new list is created every time when we call the function without providing an argument for the default parameter, but this is not the case: **Python will create the mutable object (default parameter) the first time the function is defined - not when it is called**, see the following code:\n",
"\n",
"(Original source: [http://docs.python-guide.org/en/latest/writing/gotchas/](http://docs.python-guide.org/en/latest/writing/gotchas/)"
]
@@ -549,6 +552,48 @@
],
"prompt_number": 1
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Another good example showing that demonstrates that default arguments are created when the function is created (**and not when it is called!**):"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "import time\n",
+ "def report_arg(my_default=time.time()):\n",
+ " print(my_default)\n",
+ "\n",
+ "report_arg()\n",
+ "\n",
+ "time.sleep(5)\n",
+ "\n",
+ "report_arg()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "1397764090.456688\n",
+ "1397764090.456688"
+ ]
+ },
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "\n"
+ ]
+ }
+ ],
+ "prompt_number": 10
+ },
{
"cell_type": "markdown",
"metadata": {},
@@ -1314,7 +1359,8 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "It can be really dangerous to modify a list when iterating through - it is a very common pitfall that can cause unintended behavour!"
+ "It can be really dangerous to modify a list when iterating through - it is a very common pitfall that can cause unintended behavior! \n",
+ "Look at the following examples, and for a fun exercise: try to figure out what is going on before you skip to the solution!"
]
},
{
@@ -1398,6 +1444,266 @@
}
],
"prompt_number": 7
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "
\n",
+ "
\n",
+ "\n",
+ "## Dynamic binding and typos in variable names\n",
+ "Be careful, dynamic binding is convenient, but can also quickly become dangerous!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "print('first list:')\n",
+ "for i in range(3):\n",
+ " print(i)\n",
+ " \n",
+ "print('\\nsecond list:')\n",
+ "for j in range(3):\n",
+ " print(i) # I (intentionally) made typo here!"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "first list:\n",
+ "0\n",
+ "1\n",
+ "2\n",
+ "\n",
+ "second list:\n",
+ "2\n",
+ "2\n",
+ "2\n"
+ ]
+ }
+ ],
+ "prompt_number": 14
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "
\n",
+ "
\n",
+ "\n",
+ "## List slicing using indexes that are \"out of range\""
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "As we have all encountered it 1 (x10000) time(s) in our live, the infamous `IndexError`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "my_list = [1, 2, 3, 4, 5]\n",
+ "print(my_list[5])"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "IndexError",
+ "evalue": "list index out of range",
+ "output_type": "pyerr",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\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[0mmy_list\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m3\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m4\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m5\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmy_list\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;31mIndexError\u001b[0m: list index out of range"
+ ]
+ }
+ ],
+ "prompt_number": 15
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "But suprisingly, it is not raised when we are doing list slicing, which can be a really pain for debugging:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "my_list = [1, 2, 3, 4, 5]\n",
+ "print(my_list[5:])"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "[]\n"
+ ]
+ }
+ ],
+ "prompt_number": 16
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "
\n",
+ "
\n",
+ "\n",
+ "## Reusing global variable names and `UnboundLocalErrors`"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Usually, it is no problem to access global variables in the local scope of a function:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "def my_func():\n",
+ " print(var)\n",
+ "\n",
+ "var = 'global'\n",
+ "my_func()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "global\n"
+ ]
+ }
+ ],
+ "prompt_number": 37
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "And is also no problem to use the same variable name in the local scope without affecting the local counterpart: "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "def my_func():\n",
+ " var = 'locally changed'\n",
+ "\n",
+ "var = 'global'\n",
+ "my_func()\n",
+ "print(var)"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "global\n"
+ ]
+ }
+ ],
+ "prompt_number": 38
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "But we have to be careful if we use a variable name that occurs in the global scope, and we want to access it in the local function scope if we want to reuse this name:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "def my_func():\n",
+ " print(var) # want to access global variable\n",
+ " var = 'locally changed' # but Python thinks we forgot to define the local variable!\n",
+ " \n",
+ "var = 'global'\n",
+ "my_func()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "UnboundLocalError",
+ "evalue": "local variable 'var' referenced before assignment",
+ "output_type": "pyerr",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mUnboundLocalError\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 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mvar\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'global'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0mmy_func\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;36mmy_func\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmy_func\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----> 2\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvar\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# want to access global variable\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0mvar\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'locally changed'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mvar\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'global'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;31mUnboundLocalError\u001b[0m: local variable 'var' referenced before assignment"
+ ]
+ }
+ ],
+ "prompt_number": 40
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "In this case, we have to use the `global` keyword!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "def my_func():\n",
+ " global var\n",
+ " print(var) # want to access global variable\n",
+ " var = 'locally changed' # changes the gobal variable\n",
+ "\n",
+ "var = 'global'\n",
+ "\n",
+ "my_func()\n",
+ "print(var)"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "global\n",
+ "locally changed\n"
+ ]
+ }
+ ],
+ "prompt_number": 43
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [],
+ "language": "python",
+ "metadata": {},
+ "outputs": []
}
],
"metadata": {}