{ "metadata": { "name": "scope_resolution_legb_rule" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "[Sebastian Raschka](http://www.sebastianraschka.com) \n", "last updated: 04/28/2014\n", "\n", "- [Link to the containing GitHub Repository](https://github.com/rasbt/python_reference)\n", "- [Link to this IPython Notebook on GitHub](https://github.com/rasbt/pattern_classification/blob/master/python_reference/tutorials/scope_legb_rule.ipynb)\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
raises an error\n", "\n", "**b)** \n", "
\n", "global value [ a_var outside a_func() ]\n", "\n", "**c)** \n", "
global value [ a_var in a_func() ] \n", "global value [ a_var outside a_func() ]\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[[go to solution](#solutions)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Here is why:\n", "\n", "We call `a_func()` first, which is supposed to print the value of `a_var`. According to the LEGB rule, the function will first look in its own local scope (L) if `a_var` is defined there. Since `a_func()` does not have its own `a_var`, it will look one-level above in the global scope (G) in which we defined `a_var` previously.\n", "
raises an error\n", "\n", "**b)** \n", "
local value [ a_var in a_func() ]\n", "global value [ a_var outside a_func() ]\n", "\n", "**c)** \n", "
global value [ a_var in a_func() ] \n", "global value [ a_var outside a_func() ]\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[[go to solution](#solutions)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Here is why:\n", "\n", "When we call `a_func()`, it will first look in its local scope (L) for `a_var`, since `a_var` is defined in the local scope of `a_func`, its assigned value `local variable` is printed. Note that this doesn't affect the global variable, which is in a different scope." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
global value\n", "\n", "**b)** \n", "
enclosed value\n", "\n", "**c)** \n", "
local value" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[[go to solution](#solutions)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Here is why:\n", "\n", "Let us quickly recapitulate what we just did: We called `outer()`, which defines the variable `a_var` locally (next to an existing `a_var` in the global scope). The `outer()` function then calls `inner()`, which in turn defines a variable with the name `a_var` as well. The `print()` function inside `inner()` looks in the local scope first (L->E), before it goes up the scope hierarchy, and therefore prints the value that was assigned in the local scope." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similar to the concept of the `global` keyword, which we have seen in the section above, we can use the keyword `nonlocal` inside the inner function to explicitely access a variable from the outer (enclosed) scope in order to modify its value:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a_var = 'global value'\n", "\n", "def outer():\n", " a_var = 'local value'\n", " print('outer before:', a_var)\n", " def inner():\n", " nonlocal a_var\n", " a_var = 'inner value'\n", " print('in inner():', a_var)\n", " inner()\n", " print(\"outer after:\", a_var)\n", "#outer()" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 5 }, { "cell_type": "markdown", "metadata": {}, "source": [ "
raises an error (conflict with in-built `len()` function)\n", "\n", "**b)** \n", "
called my len() function\n", "Input variable is of length 13\n", "\n", "**c)** \n", "
Input variable is of length 13" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[[go to solution](#solutions)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Here is why:\n", "\n", "Since the exact same names can be used to map names to different objects - as long as the names are in different name spaces - there is no problem of reusing the name `len` to define our own length function (this is just for demonstration pruposes, it is NOT recommended). As we go up in Python's L -> E -> G -> B hierarchy, the function `a_func()` finds `len()` in the global scope first, before it attempts to search the namespaces in the built-in scope." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "