- Notifications
You must be signed in to change notification settings - Fork 54
/
Copy pathScope.html
283 lines (250 loc) · 19.4 KB
/
Scope.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
<!DOCTYPE html>
<htmlclass="writer-html5" lang="en" >
<head>
<metacharset="utf-8" /><metacontent="Topic: variable score and namespaces in python, Difficulty: Medium, Category: Section" name="description" />
<metacontent="variable, namespace, function, scope, shadowing" name="keywords" />
<metaname="viewport" content="width=device-width, initial-scale=1.0" />
<title>Scope — Python Like You Mean It</title>
<linkrel="stylesheet" href="../_static/pygments.css" type="text/css" />
<linkrel="stylesheet" href="../_static/css/theme.css" type="text/css" />
<linkrel="stylesheet" href="../_static/my_theme.css" type="text/css" />
<!--[if lt IE 9]>
<script src="../_static/js/html5shiv.min.js"></script>
<![endif]-->
<scriptdata-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<scriptsrc="../_static/jquery.js"></script>
<scriptsrc="../_static/underscore.js"></script>
<scriptsrc="../_static/doctools.js"></script>
<scriptasync="async" src="https://www.googletagmanager.com/gtag/js?id=UA-115029372-1"></script>
<scriptsrc="../_static/gtag.js"></script>
<scriptcrossorigin="anonymous" integrity="sha256-Ae2Vz/4ePdIu6ZyI/5ZGsYnb+m0JlOmKPjt6XZ9JJkA=" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js"></script>
<script>window.MathJax={"tex": {"inlineMath": [["$","$"],["\\(","\\)"]],"processEscapes": true},"options": {"ignoreHtmlClass": "tex2jax_ignore|mathjax_ignore|document","processHtmlClass": "tex2jax_process|mathjax_process|math|output_area"}}</script>
<scriptdefer="defer" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<scriptsrc="../_static/js/theme.js"></script>
<linkrel="index" title="Index" href="../genindex.html" />
<linkrel="search" title="Search" href="../search.html" />
<linkrel="next" title="Data Structures (Part I): Introduction" href="DataStructures.html" />
<linkrel="prev" title="Basics of Functions" href="Functions.html" />
</head>
<bodyclass="wy-body-for-nav">
<divclass="wy-grid-for-nav">
<navdata-toggle="wy-nav-shift" class="wy-nav-side">
<divclass="wy-side-scroll">
<divclass="wy-side-nav-search" >
<ahref="../index.html" class="icon icon-home"> Python Like You Mean It
</a>
<divclass="version">
1.4
</div>
<divrole="search">
<formid="rtd-search-form" class="wy-form" action="../search.html" method="get">
<inputtype="text" name="q" placeholder="Search docs" />
<inputtype="hidden" name="check_keywords" value="yes" />
<inputtype="hidden" name="area" value="default" />
</form>
</div>
</div><divclass="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<pclass="caption" role="heading"><spanclass="caption-text">Table of Contents:</span></p>
<ulclass="current">
<liclass="toctree-l1"><aclass="reference internal" href="../intro.html">Python Like You Mean It</a></li>
<liclass="toctree-l1"><aclass="reference internal" href="../module_1.html">Module 1: Getting Started with Python</a></li>
<liclass="toctree-l1 current"><aclass="reference internal" href="../module_2.html">Module 2: The Essentials of Python</a><ulclass="current">
<liclass="toctree-l2"><aclass="reference internal" href="Basic_Objects.html">Basic Object Types</a></li>
<liclass="toctree-l2"><aclass="reference internal" href="SequenceTypes.html">Sequence Types</a></li>
<liclass="toctree-l2"><aclass="reference internal" href="Variables_and_Assignment.html">Variables & Assignment</a></li>
<liclass="toctree-l2"><aclass="reference internal" href="Introduction.html">Introducing Control Flow</a></li>
<liclass="toctree-l2"><aclass="reference internal" href="ConditionalStatements.html">Conditional Statements</a></li>
<liclass="toctree-l2"><aclass="reference internal" href="ForLoops.html">For-Loops and While-Loops</a></li>
<liclass="toctree-l2"><aclass="reference internal" href="Iterables.html">Iterables</a></li>
<liclass="toctree-l2"><aclass="reference internal" href="Generators_and_Comprehensions.html">Generators & Comprehension Expressions</a></li>
<liclass="toctree-l2"><aclass="reference internal" href="Itertools.html">Python’s “Itertools”</a></li>
<liclass="toctree-l2"><aclass="reference internal" href="Functions.html">Basics of Functions</a></li>
<liclass="toctree-l2 current"><aclass="current reference internal" href="#">Scope</a><ul>
<liclass="toctree-l3"><aclass="reference internal" href="#Variable-Shadowing">Variable Shadowing</a></li>
<liclass="toctree-l3"><aclass="reference internal" href="#Links-to-Official-Documentation">Links to Official Documentation</a></li>
</ul>
</li>
<liclass="toctree-l2"><aclass="reference internal" href="DataStructures.html">Data Structures (Part I): Introduction</a></li>
<liclass="toctree-l2"><aclass="reference internal" href="DataStructures_II_Dictionaries.html">Data Structures (Part II): Dictionaries</a></li>
<liclass="toctree-l2"><aclass="reference internal" href="DataStructures_III_Sets_and_More.html">Data Structures (Part III): Sets & the Collections Module</a></li>
</ul>
</li>
<liclass="toctree-l1"><aclass="reference internal" href="../module_2_problems.html">Module 2: Problems</a></li>
<liclass="toctree-l1"><aclass="reference internal" href="../module_3.html">Module 3: The Essentials of NumPy</a></li>
<liclass="toctree-l1"><aclass="reference internal" href="../module_3_problems.html">Module 3: Problems</a></li>
<liclass="toctree-l1"><aclass="reference internal" href="../module_4.html">Module 4: Object Oriented Programming</a></li>
<liclass="toctree-l1"><aclass="reference internal" href="../module_5.html">Module 5: Odds and Ends</a></li>
<liclass="toctree-l1"><aclass="reference internal" href="../changes.html">Changelog</a></li>
</ul>
</div>
</div>
</nav>
<sectiondata-toggle="wy-nav-shift" class="wy-nav-content-wrap"><navclass="wy-nav-top" aria-label="Mobile navigation menu" >
<idata-toggle="wy-nav-top" class="fa fa-bars"></i>
<ahref="../index.html">Python Like You Mean It</a>
</nav>
<divclass="wy-nav-content">
<divclass="rst-content">
<divrole="navigation" aria-label="Page navigation">
<ulclass="wy-breadcrumbs">
<li><ahref="../index.html" class="icon icon-home"></a> »</li>
<li><ahref="../module_2.html">Module 2: The Essentials of Python</a> »</li>
<li>Scope</li>
<liclass="wy-breadcrumbs-aside">
<ahref="../_sources/Module2_EssentialsOfPython/Scope.md.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<divrole="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<divitemprop="articleBody">
<style>
/* CSS overrides for sphinx_rtd_theme */
/* 24px margin */
.nbinput.nblast.container,
.nboutput.nblast.container {
margin-bottom:19px; /* padding has already 5px */
}
/* ... except between code cells! */
.nblast.container+ .nbinput.container {
margin-top:-19px;
}
.admonition>p:before {
margin-right:4px; /* make room for the exclamation icon */
}
/* Fix math alignment, see https://github.com/rtfd/sphinx_rtd_theme/pull/686 */
.math {
text-align: unset;
}
</style>
<divclass="section" id="Scope">
<h1>Scope<aclass="headerlink" href="#Scope" title="Permalink to this headline"></a></h1>
<p>A valuable aspect of the “encapsulation” provided by functions is that the function’s input argument variables, and any variables defined within the function, cannot be “seen” nor accessed outside of the function. That is, these variables are said to have a restricted <strong>scope</strong>.</p>
<divclass="admonition note">
<pclass="admonition-title fa fa-exclamation-circle"><strong>Definition</strong>:</p>
<p>The <strong>scope</strong> of a variable refers to the context in which that variable is visible/accessible to the Python interpreter.</p>
</div>
<p>Until our work with comprehension-statements and functions, we had only encountered variables that have <strong>file scope</strong>. This means that a variable, once defined, is visible to all parts of the code contained in the same file. Variables with file scope can even be accessed <em>within functions</em>. By contrast, the variables defined within a function or as input arguments to a function have a <strong>restricted scope</strong> - they can only be accessed within the context of the function:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="n">x</span><spanclass="o">=</span><spanclass="mi">3</span><spanclass="c1"># `x` has file scope. It can be even be accessed</span>
<spanclass="c1"># within a function, even if it isn't passed to</span>
<spanclass="c1"># the function as an argument</span>
<spanclass="c1"># `my_func` has file scope (after it is defined)</span>
<spanclass="k">def</span><spanclass="nf">my_func</span><spanclass="p">(</span><spanclass="n">y</span><spanclass="p">):</span>
<spanclass="n">func_var</span><spanclass="o">=</span><spanclass="mi">9</span><spanclass="o">+</span><spanclass="n">x</span><spanclass="c1"># `x` will have the value 3</span>
<spanclass="c1"># the scope of `y` and `func_var` is restricted to this function</span>
<spanclass="k">return</span><spanclass="n">y</span>
<spanclass="c1"># `func_var` and `y` do not exist here</span>
<spanclass="nb">print</span><spanclass="p">(</span><spanclass="n">func_var</span><spanclass="p">)</span><spanclass="c1"># raises NameError: name `func_var` not defined</span>
<spanclass="nb">print</span><spanclass="p">(</span><spanclass="n">y</span><spanclass="p">)</span><spanclass="c1"># raises NameError: name `y` not defined</span>
</pre></div>
</div>
<p>Python’s scoping rules are quite liberal compared to those of other languages, like C++. In most situations, Python will give variables file scope. Let’s briefly survey the various contexts in which variables are defined, along with their corresponding scoping rules. Assume that the following code represents the entire contents of the Python script “example_scope.py”:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># this demonstrates scope of variables in different contexts</span>
<spanclass="c1"># nothing meaningful is computed in this file</span>
<spanclass="kn">from</span><spanclass="nn">itertools</span><spanclass="kn">import</span><spanclass="n">combinations</span><spanclass="c1"># `combinations` has file scope</span>
<spanclass="c1"># `my_func` has file scope</span>
<spanclass="c1"># `in_arg1` has restricted scope</span>
<spanclass="c1"># `in_arg2` has restricted scope</span>
<spanclass="c1"># `func_block` has restricted scope</span>
<spanclass="k">def</span><spanclass="nf">my_func</span><spanclass="p">(</span><spanclass="n">in_arg1</span><spanclass="p">,</span><spanclass="n">in_arg2</span><spanclass="o">=</span><spanclass="s2">"cat"</span><spanclass="p">):</span>
<spanclass="n">func_block</span><spanclass="o">=</span><spanclass="mi">1</span>
<spanclass="k">return</span><spanclass="kc">None</span>
<spanclass="c1"># `file_var` has file scope</span>
<spanclass="c1"># `comp_var` has restricted scope</span>
<spanclass="n">file_var</span><spanclass="o">=</span><spanclass="p">[</span><spanclass="n">comp_var</span><spanclass="o">**</span><spanclass="mi">2</span><spanclass="k">for</span><spanclass="n">comp_var</span><spanclass="ow">in</span><spanclass="p">[</span><spanclass="o">-</span><spanclass="mi">1</span><spanclass="p">,</span><spanclass="o">-</span><spanclass="mi">2</span><spanclass="p">]]</span>
<spanclass="c1"># `if_block` has file scope</span>
<spanclass="k">if</span><spanclass="kc">True</span><spanclass="p">:</span>
<spanclass="n">if_block</span><spanclass="o">=</span><spanclass="mi">2</span>
<spanclass="k">else</span><spanclass="p">:</span>
<spanclass="n">if_block</span><spanclass="o">=</span><spanclass="mi">3</span>
<spanclass="c1"># `it_var` has file scope</span>
<spanclass="c1"># `for_block` has file scope</span>
<spanclass="k">for</span><spanclass="n">it_var</span><spanclass="ow">in</span><spanclass="p">[</span><spanclass="mi">1</span><spanclass="p">,</span><spanclass="mi">2</span><spanclass="p">,</span><spanclass="mi">3</span><spanclass="p">]:</span>
<spanclass="n">for_block</span><spanclass="o">=</span><spanclass="mi">1</span>
<spanclass="c1"># `while_block` has file scope</span>
<spanclass="k">while</span><spanclass="kc">True</span><spanclass="p">:</span>
<spanclass="n">while_block</span><spanclass="o">=</span><spanclass="kc">None</span>
<spanclass="k">break</span>
</pre></div>
</div>
<p>In the preceding code, the following variables have <em>file scope</em>:</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">combinations</span></code></p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">my_func</span></code></p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">file_var</span></code></p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">if_block</span></code></p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">it_var</span></code></p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">for_block</span></code></p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">while_block</span></code></p></li>
</ul>
<p>whereas the following variables have <em>restricted scope</em>:</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">in_arg1</span></code></p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">in_arg2</span></code></p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">func_block</span></code></p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">comp_var</span></code></p></li>
</ul>
<p>In C++, the variables <codeclass="docutils literal notranslate"><spanclass="pre">if_block</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">it_var</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">for_block</span></code>, and <codeclass="docutils literal notranslate"><spanclass="pre">while_block</span></code> all would have had restricted scopes - these variables would not be defined outside of their respective if/for/while blocks.</p>
<divclass="admonition note">
<pclass="admonition-title fa fa-exclamation-circle"><strong>Takeaway</strong>:</p>
<p>Variables defined within a function have a <em>restricted scope</em> such that they do not exist outside of that function. Most other contexts for defining variables in Python produce variables with <em>file scope</em> (i.e. they can be accessed anywhere in the file’s code, subsequent to their definition).</p>
</div>
<divclass="section" id="Variable-Shadowing">
<h2>Variable Shadowing<aclass="headerlink" href="#Variable-Shadowing" title="Permalink to this headline"></a></h2>
<p>What happens when a file-scope variable and a function-scope variable share the same name? This type of circumstance is known as <strong>variable shadowing</strong>. Python resolves this by giving precedence to the variable <em>with the most restricted scope</em>, when inside that scope:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="n">x</span><spanclass="o">=</span><spanclass="mi">2</span>
<spanclass="n">y</span><spanclass="o">=</span><spanclass="mi">3</span>
<spanclass="k">def</span><spanclass="nf">func</span><spanclass="p">(</span><spanclass="n">x</span><spanclass="p">):</span>
<spanclass="c1"># input-arg `x` overrides file-scope version of `x`</span>
<spanclass="n">y</span><spanclass="o">=</span><spanclass="mi">5</span><spanclass="c1"># overrides file-scope version of `y`</span>
<spanclass="k">return</span><spanclass="n">x</span><spanclass="o">+</span><spanclass="n">y</span>
<spanclass="c1"># `x` is 2 here, once again</span>
<spanclass="c1"># `y` is 3 here, once again</span>
<spanclass="nb">print</span><spanclass="p">(</span><spanclass="n">func</span><spanclass="p">(</span><spanclass="o">-</span><spanclass="mi">5</span><spanclass="p">))</span><spanclass="c1"># prints 0</span>
<spanclass="nb">print</span><spanclass="p">(</span><spanclass="n">x</span><spanclass="p">,</span><spanclass="n">y</span><spanclass="p">)</span><spanclass="c1"># prints 2 3</span>
</pre></div>
</div>
<p>and similarly,</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="n">it</span><spanclass="o">=</span><spanclass="s2">"cow"</span>
<spanclass="k">def</span><spanclass="nf">func</span><spanclass="p">():</span>
<spanclass="n">it</span><spanclass="o">=</span><spanclass="s2">"dog"</span><spanclass="c1"># overrides file-scope version of `it`</span>
<spanclass="n">my_list</span><spanclass="o">=</span><spanclass="p">[</span><spanclass="n">it</span><spanclass="o">**</span><spanclass="mi">2</span><spanclass="k">for</span><spanclass="n">it</span><spanclass="ow">in</span><spanclass="p">[</span><spanclass="mi">1</span><spanclass="p">,</span><spanclass="mi">2</span><spanclass="p">,</span><spanclass="mi">3</span><spanclass="p">]]</span><spanclass="c1"># within the list comprehension, the func-scope `it` is overridden</span>
<spanclass="c1"># `it` is "dog" here, once again</span>
<spanclass="k">return</span><spanclass="kc">None</span>
<spanclass="c1"># `it` is "cow" here, once again</span>
</pre></div>
</div>
</div>
<divclass="section" id="Links-to-Official-Documentation">
<h2>Links to Official Documentation<aclass="headerlink" href="#Links-to-Official-Documentation" title="Permalink to this headline"></a></h2>
<ulclass="simple">
<li><p><aclass="reference external" href="https://docs.python.org/3/tutorial/classes.html#python-scopes-and-namespaces">Scopes and namespaces</a></p></li>
<li><p><aclass="reference external" href="https://docs.python.org/3/reference/executionmodel.html">Python’s execution model</a></p></li>
</ul>
</div>
</div>
</div>
</div>
<footer><divclass="rst-footer-buttons" role="navigation" aria-label="Footer">
<ahref="Functions.html" class="btn btn-neutral float-left" title="Basics of Functions" accesskey="p" rel="prev"><spanclass="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
<ahref="DataStructures.html" class="btn btn-neutral float-right" title="Data Structures (Part I): Introduction" accesskey="n" rel="next">Next <spanclass="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
</div>
<hr/>
<divrole="contentinfo">
<p>© Copyright 2021, Ryan Soklaski.</p>
</div>
Built with <ahref="https://www.sphinx-doc.org/">Sphinx</a> using a
<ahref="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <ahref="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function(){
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>