{"id":6129,"date":"2012-11-05T20:06:20","date_gmt":"2012-11-06T01:06:20","guid":{"rendered":"http:\/\/cscircles.cemc.uwaterloo.ca\/?page_id=6129"},"modified":"2019-03-05T03:59:51","modified_gmt":"2019-03-05T08:59:51","slug":"11b-variable-scope-nl","status":"publish","type":"page","link":"https:\/\/cscircles.cemc.uwaterloo.ca\/dev\/11b-variable-scope-nl\/","title":{"rendered":"11B: De scope van een variabele"},"content":{"rendered":"<p><em>Les 11 kent drie delen A, B, C die in een willekeurige volgorde kunnen worden doorgewerkt.<\/em><\/p>\n<p>In deze les leggen we het begrip <em>scope (geldigheidsgebied) van een variabele<\/em> uit. Het belangrijkste idee is, dat het mogelijk is om twee <em>verschillende<\/em> variabelen te hebben met <em>dezelfde<\/em> naam maar verschillende \"scopes\". Dit maakt het makkelijker om programma's te schrijven en te verbeteren, in het bijzonder grote programma's.<\/p>\n<h2>Een voorbeeld van een \"scope\" van een variabele<\/h2>\n<p>In dit voorbeeld is een deel van ons programma de volgende functie:<\/p>\n<pre>def square(x):\r\n \u00a0 value = x * x\r\n \u00a0 return value<\/pre>Dit is de functie die het kwadraat van het getal <code>x<\/code> berekent; bijvoorbeeld:\u00a0<code>square(5)<\/code> geeft <code>25<\/code> als resultaatwaarde. Veronderstel dat we <code>square<\/code> aanroepen vanuit een ander deel van het programma waarin een variabele\u00a0<code>value<\/code>\u00a0voor een ander doel wordt gebruikt:<\/p>\n<pre># hier begint het hoofdprogramma\r\nvalue = 17\r\nfivesquared = square(5)\r\nprint(fivesquared, value)<\/pre>De vraag is wat er in dit scenario zal worden afgedrukt? Er zijn twee mogelijkheden, wanneer we niet weten hoe Python werkt:<\/p>\n<ol>\n<li>Een mogelijkheid is dat Python herkent dat de twee<code>value<\/code>-variabelen op de een of andere manier \"gescheiden moeten worden\". Dus, de aanroep van<code>square<\/code>zal 25 teruggeven, maar de waarde van<code>value<\/code>in het hoofdprogramma blijft 17, en we zien als uitvoer afgedrukt worden\u00a0<code>25\u00a0<\/code><code>17<\/code>.<\/li>\n<li>De andere mogelijkheid is dat bij het uitvoeren van <code>square<\/code>, het de bestaande waarde van <code>value<\/code> overschrijft met 25, en we als uitvoer krijgen\u00a0<code>25\u00a0<\/code><code>25<\/code>.<\/li>\n<\/ol>\n<p>Laten we nagaan wat er daadwerkelijk gebeurt!<\/p>\n<p><iframe width='100%' height='480' frameborder='0' scrolling='no' src='https:\/\/cscircles.cemc.uwaterloo.ca\/dev\/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+het+hoofdprogramma+begint+hier+%0Avalue+%3D+17+%0Avijf_kwadraat+%3D+square%285%29+%0Aprint%28vijf_kwadraat%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 zien dat het gedrag van Python overeenkomt met de beschrijving in mogelijkheid nr 1. Het zit zo:\u00a0<em>wanneer je een functie aanroept, kun je geen variabelen wijzigen die buiten de functie zijn gedefinieerd.<\/em> In plaats daarvan zullen alle toekenningsopdrachten inwerken op een \"lokale\" variabele die enkel bestaat binnen de huidige functie-oproep. Meer bepaald: wanneer Python begint met een functie uit te voeren, maakt het een nieuw\u00a0<em>frame<\/em> aan speciaal voor die uitvoering van die functie. Alle toekenningen die binnen die uitvoering gebeuren, komen terecht in dat frame. Het frame verdwijnt, en alle lokale variabelen gaan onherroepelijk verloren, wanneer de functie-uitvoering eindigt. De <strong>reden<\/strong>\u00a0dat Python en de meeste andere talen werken met frames, is dat het daardoor veel gemakkelijker is grote programma's te schrijven met vele functies. In het bijzonder is het daardoor mogelijk een nieuwe functie te schrijven en daarin elke willekeurige variabelenaam te gebruiken (inclusief de gewone zoals\u00a0<code>result,<\/code>\u00a0<code>temp<\/code>\u00a0en\u00a0<code>i<\/code>) zelfs wanneer zij elders voor andere doelen worden gebruikt.<\/p>\n<p>Kijk naar \"Step 6 van 8\" hierboven. Merk op dat er twee verschillende variabelen zijn met de naam <em>value<\/em>: \u00e9\u00e9n geassocieerd met de huidige uitvoering van functie <code>square<\/code>, en \u00e9\u00e9n daarbuiten (in het \"globale\" <em>frame<\/em>).<\/p>\n<div class='pybox modeNeutral' id='pybox0'>\n<img title='You have not yet completed this problem.' src='https:\/\/cscircles.cemc.uwaterloo.ca\/dev\/wp-content\/plugins\/pybox\/files\/icon.png' class='pycheck'\/><div class=\"heading\"><span class='type'>Multiple Choice Exercise: <\/span><span class='title'>Erbinnen en erbuiten<\/span><\/div><div>Wat is de uitvoer van het volgende programma? <\/p>\n<pre>x = \"erbuiten\"<br\/>def xReplace(value):<br\/> \u00a0 x = value<br\/>xReplace(\"erbinnen\")<br\/>print(x)<\/pre> <\/div><label>Your choice: <\/label><select id=\"pyselect0\"><option value=\"d\" selected>Select one<\/option><option value=\"r\">erbuiten<\/option><option value=\"w\">Het programma geeft een fout.<\/option><option value=\"w\">erbinnen<\/option><\/select><div class='pyboxbuttons'><input type=\"hidden\" name=\"lang\" value=\"\"\/><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! De opdracht <code>x = value<\/code> verandert alleen de lokale versie van variabele <code>x<\/code> geassocieerd met de uitvoering van de functie. De globale <code>x<\/code> verandert niet (en de functie <code>xReplace<\/code> is dus nutteloos en verandert nooit iets).<\/div><\/div>\n<p>Een vergelijkbaar concept als een\u00a0<em>scope<\/em>\u00a0is een\u00a0<em>namespace;<\/em>\u00a0een namespace is een soort scope voor een module. Dus als je een module importeert (zoals met bijvoorbeeld\u00a0<code>import math<\/code>) overlapt een variabele gedefinieerd door die module (zoals <code>math.pi<\/code>) niet met een variabele\u00a0<code>pi<\/code>\u00a0in je eigen programma, omdat ze verschillende namespaces hebben. (Als je echter <code>import pi from math<\/code> gebruikt, zal wel een eigen globale variabele overschreven worden.)<\/p>\n<h2>Regels voor scopes: globaal en lokaal<\/h2>\n<p>Er zijn situaties waarin we variabelen van globale en lokale scope door elkaar willen gebruiken. Een voorbeeldje is als je een bepaalde variabele eenmalig een waarde wil geven aan het begin van het programma, maar je wil deze variabele nog wel gebruiken in de rest van je programma.<\/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>Een globale functie binnen een functie uitlezen<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'>\nfavorietePizza='hawaii'\ndef bestelPizzas(n):\n   print(\"Ik wil graag \", str(n), \"pizza's\", favorietePizza)\nbestelPizzas(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=\"\"\/><input type=\"hidden\" id=\"inputInUse1\" name=\"inputInUse\" value=\"Y\"\/>\n<input type=\"hidden\" name=\"pyId\" value=\"1\"\/>\n<input type=\"hidden\" name=\"hash\" value=\"ddaaab7a0aef6e2d9ddcc66e10d5d058\"\/>\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>De lokale scope bevat hier geen variabele genaamd <code>favorietePizza<\/code>, <em>maar dit leidt niet tot een foutmelding<\/em>. Wanneer Python een variabele in de lokale scope niet kan vinden wordt gekeken of er in de globale scope wel een variabele met die naam bestaat. In dit geval wordt <code>favorietePizza<\/code> inderdaad in de globale scope gevonden.<\/p>\n<p><table class='pywarn'><tr><td class='pywarnleft'><img src='https:\/\/cscircles.cemc.uwaterloo.ca\/dev\/wp-content\/plugins\/pybox\/files\/warning.png'\/><\/td><td class='pywarnright'><span> In de bovenstaande voorbeelden zijn <code>bestelPizzas<\/code> en <code>xReplace<\/code> syntactisch bijna helemaal identiek. Waarom maakt Python een lokale variabele <code>x<\/code> in <code>xReplace<\/code>, maar geen nieuwe <code>favorietePizza<\/code> in <code>bestelPizzas<\/code>? De regel in Python is als volgt: als je alleen leest uit de variabele wordt er geen nieuwe lokale variabele gemaakt; schrijf je echter ergens in de functie naar de variabele, dan wordt deze variabele in de hele functie als lokaal beschouwd. (Dit is de meest voorkomende oorzaak van de foutmelding <a href=\"https:\/\/cscircles.cemc.uwaterloo.ca\/dev\/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>: zie ook [<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\">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\">2<\/a>] in de offici\u00eble Python-documentatie.) <\/span><\/td><\/table><\/p>\n<p>Functie-argumenten worden <em>altijd<\/em> als lokale variabelen beschouwd:<\/p>\n<p><iframe width='100%' height='480' frameborder='0' scrolling='no' src='https:\/\/cscircles.cemc.uwaterloo.ca\/dev\/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>Het gebruik van <code>global<\/code><\/h2>\n<p>Zoals zo vaak werkt bovenstaande aanpak in 99% van de gevallen. Er zijn echter gevallen te bedenken waar je echt de waarde van een globale variabele wilt veranderen binnen een functie. Python stelt je in staat dit te doen door middel van de opdracht<code>global<\/code>. Hieronder staat een aangepaste versie van het eerdere <code>xReplace<\/code>-voorbeeld.<\/p>\n<p><iframe width='100%' height='480' frameborder='0' scrolling='no' src='https:\/\/cscircles.cemc.uwaterloo.ca\/dev\/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>Zoals we eerder besproken vereist <em>lezen<\/em> van een variabele niet dat je <code>global<\/code> gebruikt; dit is alleen nodig als je wilt <em>schrijven<\/em>.<\/p>\n<p>Je hebt deze les nu afgerond en kun je door naar de volgende.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Les 11 kent drie delen A, B, C die in een willekeurige volgorde kunnen worden doorgewerkt. In deze les leggen we het begrip scope (geldigheidsgebied) van een variabele uit. Het belangrijkste idee is, dat het mogelijk is om twee verschillende &hellip; <a href=\"https:\/\/cscircles.cemc.uwaterloo.ca\/dev\/11b-variable-scope-nl\/\">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-6129","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/cscircles.cemc.uwaterloo.ca\/dev\/wp-json\/wp\/v2\/pages\/6129","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cscircles.cemc.uwaterloo.ca\/dev\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/cscircles.cemc.uwaterloo.ca\/dev\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/cscircles.cemc.uwaterloo.ca\/dev\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cscircles.cemc.uwaterloo.ca\/dev\/wp-json\/wp\/v2\/comments?post=6129"}],"version-history":[{"count":30,"href":"https:\/\/cscircles.cemc.uwaterloo.ca\/dev\/wp-json\/wp\/v2\/pages\/6129\/revisions"}],"predecessor-version":[{"id":11217,"href":"https:\/\/cscircles.cemc.uwaterloo.ca\/dev\/wp-json\/wp\/v2\/pages\/6129\/revisions\/11217"}],"wp:attachment":[{"href":"https:\/\/cscircles.cemc.uwaterloo.ca\/dev\/wp-json\/wp\/v2\/media?parent=6129"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}