{"id":1574,"date":"2011-02-20T13:42:05","date_gmt":"2011-02-20T13:42:05","guid":{"rendered":"http:\/\/cemclinux1.math.uwaterloo.ca\/~cscircles\/wordpress\/"},"modified":"2011-02-20T13:42:05","modified_gmt":"2011-02-20T13:42:05","slug":"11b-how-functions-work","status":"publish","type":"page","link":"https:\/\/olescs.hkmu.edu.hk\/python\/11b-how-functions-work\/","title":{"rendered":"11B: Variable Scope"},"content":{"rendered":"<!-- Please retain this notice and add more notes if you create a new version.<br \/>\nOriginal lesson author: David Pritchard, daveagp@gmail.com, http:\/\/cscircles.ca<br \/>\nLicense: http:\/\/creativecommons.org\/licenses\/by-nc-sa\/3.0\/-->\n<p><em>Lesson 11 has three parts A, B, C which can be completed in any order.<\/em><\/p>\n<p>In this lesson we explain a concept called <em>variable scope<\/em>. The main idea is that it is possible to have two <em>different<\/em> variables with the <em>same<\/em> name whenever they have different scopes. This makes it much easier to write and edit programs, especially large ones. It is also a necessary ingredient in a later topic, recursion.<\/p>\n<h2>An example of variable scope<\/h2>\n<p>For this example, part of our program will be the following function:<\/p>\n<pre>def square(x):\n   value = x * x\n   return value<\/pre>This is a function which computes the square of the number\u00a0<code>x<\/code>, for example\u00a0<code>square(5)<\/code> returns <code>25<\/code>. Now suppose we call <code>square<\/code> from another part of the program which also uses a <code>value<\/code> variable for\u00a0another purpose:<\/p>\n<pre># main body of the program starts here\nvalue = 17\nfivesquared = square(5)\nprint(fivesquared, value)<\/pre>The question is, what will be printed in this scenario? There are two possibilities, if we don't know how Python works:<\/p>\n<ol>\n<li>One possibility is that Python recognizes that the two <code>value<\/code> variables should be \"kept separate\" somehow. Thus, the call to <code>square<\/code> will return 25, but the value of <code>value<\/code> in the main body will stay at 17, and we see the output\u00a0<code>25\u00a0<\/code><code>17<\/code>.<\/li>\n<li>The other possibility is that when <code>square<\/code>, executes, it over-writes the existing value of <code>value<\/code> with 25, and we see the output\u00a0<code>25\u00a0<\/code><code>25<\/code>.<\/li>\n<\/ol>\n<p>Let's see what actually happens!<\/p>\n<p><iframe width='100%' height='480' frameborder='0' scrolling='no' src='https:\/\/olescs.hkmu.edu.hk\/python\/wp-content\/plugins\/pybox\/OnlinePythonTutor3-cemc\/iframe-embed.html#code=def+square%28x%29%3A%0A++++value+%3D+x+%2A+x%0A++++return+value%0A%0A%23+main+body+of+the+program+starts+here%0Avalue+%3D+17%0Afivesquared+%3D+square%285%29%0Aprint%28fivesquared%2C+value%29&cumulative=false&heapPrimitives=false&drawParentPointers=false&textReferences=false&showOnlyOutputs=false&py=3&curInstr=0&resizeContainer=true&highlightLines&width=450&rightStdout=1'><\/iframe><\/p>\n<p>We see that Python's behaviour is consistent with possibility #1. In fact,\u00a0<em>whenever you call a function, you cannot affect any variables defined outside the function.<\/em> Instead, any statements that assign values to variables affect only a \"local\" variable which is \"inside\" the function call.\u00a0The <strong>reason<\/strong> that Python, and most other languages, work like this is that it makes it much more simple to write long programs with many functions. In particular, when we define a new function, we are always allowed to use any variable names inside the function\u00a0(including common ones like <code>result,<\/code>\u00a0<code>temp<\/code>\u00a0and <code>i<\/code>) even if they are being used somewhere else for different purposes.<\/p>\n<p>To see this in detail, look at \"Step 6 of 8\" in the visualizer. Notice that there are two different <code>value<\/code> variables: one inside of the <code>square<\/code> function, and one outside (in the \"global\" area).<\/p>\n<div class='pybox modeNeutral' id='pybox0'>\n<img title='You have not yet completed this problem.' src='https:\/\/olescs.hkmu.edu.hk\/python\/wp-content\/plugins\/pybox\/files\/icon.png' class='pycheck'\/><div class=\"heading\"><span class='type'>Multiple Choice Exercise: <\/span><span class='title'>Inner and Outer<\/span><\/div><div>What is the output of the following program? <\/p>\n<pre>x = \"outer\"<br\/>def xReplace(value):<br\/>   x = value<br\/>xReplace(\"inner\")<br\/>print(x)<\/pre> <\/div><label>Your choice: <\/label><select id=\"pyselect0\"><option value=\"d\" selected>Select one<\/option><option value=\"r\">outer<\/option><option value=\"w\">inner<\/option><option value=\"w\">The program causes an error.<\/option><\/select><div class='pyboxbuttons'><input type=\"hidden\" name=\"lang\" value=\"en-US\"\/><input type=\"hidden\" name=\"slug\" value=\"11b.inout\"\/><input type='submit' style='margin:5px;' value='Check answer' onClick='pbMultiCheck(0)'\/><\/div><div class=\"pbresults\" id=\"pyMultiResults0\"><\/div><div class=\"epilogue\">Correct! The statement <code>x = value<\/code> only affects the local version of variable <code>x<\/code> inside the function. The global version of <code>x<\/code> does not change. (So, the function <code>xReplace<\/code> is useless and never has any effect.)<\/div><\/div>\n<p>Another similar concept to\u00a0<em>scope<\/em>\u00a0is a\u00a0<em>namespace;<\/em>\u00a0a namespace is like a scope for a package. So even if you\u00a0<code>import<\/code>\u00a0a package (such as <code>math<\/code>) which uses variable name\u00a0<code>x<\/code>\u00a0somewhere, it does not overlap with the variable\u00a0<code>x<\/code>\u00a0used by your program, since they lie in different namespaces.<\/p>\n<h2>Scoping Rules: Seeing Out<\/h2>\n<p>There are situations where we want to mix variables from local and global scopes. One common example is where you have some common variable initialized once at the start of the program, but you also want your functions to be able to read the variable.<\/p>\n<p><form class=\"pbform\" action=\"#\" id=\"pbform1\" method=\"POST\">\n<div class='pybox modeNeutral  facultative' id='pybox1'>\n<div class=\"heading\"><span class=\"title\">Example<\/span><\/div>Reading a global variable from inside a function<div class='pyboxTextwrap pyboxCodewrap RO '  style='height: 110px;'><textarea wrap='off' name='usercode1' id='usercode1'  cols=10 rows=4 readonly='readonly'  style = 'height : 110px;'  class='pyboxCode RO'>\nfavouriteTopping='pepperoni'\ndef orderPizzas(n):\n   print(\"I'd like\", str(n), favouriteTopping, \"pizzas\")\norderPizzas(3)<\/textarea><\/div>\n<div id='pbhistory1' class='flexcontain' style='display:none;'><\/div>\n<div class='pyboxbuttons'><table><tr>\n<td><input type='submit' name='submit' id='submit1' value=' '\/><\/td>\n<td><input type='button' name='consolecopy' value=\"Open in console\" onclick=\"pbConsoleCopy(1)\" ><\/td>\n<td><input type='button' name='visualize' value=\"Visualize\" onclick=\"pbVisualize(1,'N')\" ><\/td>\n<\/tr><\/table><\/div>\n<input type=\"hidden\" name=\"lang\" value=\"en-US\"\/><input type=\"hidden\" id=\"inputInUse1\" name=\"inputInUse\" value=\"Y\"\/>\n<input type=\"hidden\" name=\"pyId\" value=\"1\"\/>\n<input type=\"hidden\" name=\"hash\" value=\"ebcc525a96b4049fa07a711b4c4a3ea4\"\/>\n<div id='pbresults1' class='pbresults'><\/div>\n<\/div>\n<\/form>\n<script type='text\/javascript'>document.getElementById(\"submit1\").value = \"Run program\";document.getElementById(\"inputInUse1\").value = \"N\";<\/script>\n<\/p>\n<p>Here, the local scope did not contain a variable named <code>favouriteTopping<\/code>, <em>but this did not cause an error<\/em>. Python's rule for evaluating variables is that, if a variable needs to be evaluated which does not exist in the local scope, then it looks for it in the global scope. In our case, it indeed found <code>favouriteTopping<\/code> in the global scope. (In a more general case with one function body calling another function you would have three scopes; Python always checks the \"localmost\" first and goes one step at a time to the global scope until the variable is found.)<\/p>\n<p><table class='pywarn'><tr><td class='pywarnleft'><img src='https:\/\/olescs.hkmu.edu.hk\/python\/wp-content\/plugins\/pybox\/files\/warning.png'\/><\/td><td class='pywarnright'><span> Two of the examples above, with <code>orderPizzas<\/code> and <code>xReplace<\/code>, are almost syntactically identical. Why does Python create a new local variable <code>x<\/code> in <code>xReplace<\/code>, but no new\u00a0<code>favouriteTopping<\/code> in <code>orderPizzas<\/code>? Python's rule is the following: if you only read from the variable, then no new local variable is created; but if you write to the variable even once, then the variable is treated as local throughout the function body. (This is the most common cause of <a href=\"https:\/\/olescs.hkmu.edu.hk\/python\/console\/?consolecode=x%20%3D%201%0Adef%20f%28%29%3A%0A%20%20%20print%28x%29%0A%20%20%20x%20%3D%202%0Af%28%29\" target=\"_blank\"><code>UnboundLocalError<\/code><\/a>:\u00a0see these two questions [<a href=\"http:\/\/docs.python.org\/py3k\/faq\/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value\" target=\"_blank\" rel=\"noopener noreferrer\">1<\/a>, <a href=\"http:\/\/docs.python.org\/py3k\/faq\/programming.html#what-are-the-rules-for-local-and-global-variables-in-python\" target=\"_blank\" rel=\"noopener noreferrer\">2<\/a>] in the official Python documentation.) <\/span><\/td><\/table><\/p>\n<p>Function arguments are <em>always<\/em> treated as new local variables, as the following\u00a0broken code fragment illustrates (it attempts to reset the variable\u00a0<code>g<\/code>\u00a0to\u00a0<code>0<\/code>, but fails).<\/p>\n<p><iframe width='100%' height='480' frameborder='0' scrolling='no' src='https:\/\/olescs.hkmu.edu.hk\/python\/wp-content\/plugins\/pybox\/OnlinePythonTutor3-cemc\/iframe-embed.html#code=def+resetToZero%28var%29%3A%0A+var+%3D+0%0Ag+%3D+15%0AresetToZero%28g%29%0Aprint%28g%29&cumulative=false&heapPrimitives=false&drawParentPointers=false&textReferences=false&showOnlyOutputs=false&py=3&curInstr=0&resizeContainer=true&highlightLines&width=400&rightStdout=1'><\/iframe><\/p>\n<h2><code>global<\/code>\u00a0Changes<\/h2>\n<p>Like many other things, the normal flow described above works for 99% of all situations. But that remaining 1% of the time, you really might want to change a global variable from within a function. Python allows you to do this using the <code>global<\/code> statement.<\/p>\n<p>Here's a modification of the earlier <code>xReplace<\/code> example. Note that we declaring the variable as\u00a0<code>global<\/code>\u00a0in the function. This lets you change the global value from within the function.<\/p>\n<p><iframe width='100%' height='480' frameborder='0' scrolling='no' src='https:\/\/olescs.hkmu.edu.hk\/python\/wp-content\/plugins\/pybox\/OnlinePythonTutor3-cemc\/iframe-embed.html#code=def+xReplace%28value%29%3A%0A++++global+x%0A++++x+%3D+value%0A%0Ax+%3D+%22outer%22%0AxReplace%28%22inner%22%29+%0Aprint%28x%29+++++++%23+%27inner%27+now%21&cumulative=false&heapPrimitives=false&drawParentPointers=false&textReferences=false&showOnlyOutputs=false&py=3&curInstr=0&resizeContainer=true&highlightLines&width=400&rightStdout=1'><\/iframe><\/p>\n<p>Reiterating: when inside of a function, assigning to a variable name defined at global scope actually creates a separate new local-scope variable with the same name, instead of modifying the global-scope variable (like <code>resetToZero<\/code>). If you want to update the global-scope variable,\u00a0you must include the statement <code>global \u00abvariable-name\u00bb<\/code>\u00a0inside of the function (like the fixed <code>xReplace<\/code> example). Then Python understands that changes to <code>\u00abvariable-name\u00bb<\/code> in the function are meant to refer to the existing global-scope variable.<\/p>\n<p>As we mentioned earlier, <em>reading<\/em> a global variable does not require using the <code>global<\/code> statement; only <em>writing<\/em>. That concludes the lesson!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Lesson 11 has three parts A, B, C which can be completed in any order. In this lesson we explain a concept called variable scope. The main idea is that it is possible to have two different variables with the &hellip; <a href=\"https:\/\/olescs.hkmu.edu.hk\/python\/11b-how-functions-work\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1574","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/olescs.hkmu.edu.hk\/python\/wp-json\/wp\/v2\/pages\/1574"}],"collection":[{"href":"https:\/\/olescs.hkmu.edu.hk\/python\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/olescs.hkmu.edu.hk\/python\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/olescs.hkmu.edu.hk\/python\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/olescs.hkmu.edu.hk\/python\/wp-json\/wp\/v2\/comments?post=1574"}],"version-history":[{"count":0,"href":"https:\/\/olescs.hkmu.edu.hk\/python\/wp-json\/wp\/v2\/pages\/1574\/revisions"}],"wp:attachment":[{"href":"https:\/\/olescs.hkmu.edu.hk\/python\/wp-json\/wp\/v2\/media?parent=1574"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}