forked from rsokl/Learning_Python
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathMethods.html
More file actions
497 lines (364 loc) · 37.8 KB
/
Copy pathMethods.html
File metadata and controls
497 lines (364 loc) · 37.8 KB
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
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta content="Topic: The different kinds of class methods, Difficulty: Medium, Category: Section" name="description" />
<meta content="instance, class method, static method, property, abstract method, class funtion" name="keywords" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Methods — Python Like You Mean It</title>
<script type="text/javascript" src="../_static/js/modernizr.min.js"></script>
<script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script src="https://www.googletagmanager.com/gtag/js?id=UA-115029372-1"></script>
<script src="../_static/gtag.js"></script>
<script crossorigin="anonymous" integrity="sha256-Ae2Vz/4ePdIu6ZyI/5ZGsYnb+m0JlOmKPjt6XZ9JJkA=" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js"></script>
<script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script type="text/x-mathjax-config">MathJax.Hub.Config({"tex2jax": {"inlineMath": [["$", "$"], ["\\(", "\\)"]], "processEscapes": true, "ignoreClass": "document", "processClass": "math|output_area"}})</script>
<script type="text/javascript" src="../_static/js/theme.js"></script>
<link rel="stylesheet" href="../_static/css/theme.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="../_static/my_theme.css" type="text/css" />
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Applications of Object Oriented Programming" href="Applications_of_OOP.html" />
<link rel="prev" title="A Brief Summary of Terms and Concepts" href="Brief_Review.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="../index.html" class="icon icon-home"> Python Like You Mean It
</a>
<div class="version">
1.4
</div>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
<p class="caption"><span class="caption-text">Table of Contents:</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../intro.html">Python Like You Mean It</a></li>
<li class="toctree-l1"><a class="reference internal" href="../module_1.html">Module 1: Getting Started with Python</a></li>
<li class="toctree-l1"><a class="reference internal" href="../module_2.html">Module 2: The Essentials of Python</a></li>
<li class="toctree-l1"><a class="reference internal" href="../module_2_problems.html">Module 2: Problems</a></li>
<li class="toctree-l1"><a class="reference internal" href="../module_3.html">Module 3: The Essentials of NumPy</a></li>
<li class="toctree-l1"><a class="reference internal" href="../module_3_problems.html">Module 3: Problems</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="../module_4.html">Module 4: Object Oriented Programming</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="Introduction_to_OOP.html">Introduction to Object Oriented Programming</a></li>
<li class="toctree-l2"><a class="reference internal" href="ClassDefinition.html">Defining a New Class of Object</a></li>
<li class="toctree-l2"><a class="reference internal" href="ClassInstances.html">Instances of a Class</a></li>
<li class="toctree-l2"><a class="reference internal" href="Brief_Review.html">A Brief Summary of Terms and Concepts</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#">Methods</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#Instance-Methods">Instance Methods</a><ul>
<li class="toctree-l4"><a class="reference internal" href="#The-self-Argument">The <code class="docutils literal notranslate"><span class="pre">self</span></code> Argument</a></li>
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="#Class-Methods">Class Methods</a></li>
<li class="toctree-l3"><a class="reference internal" href="#Static-Methods">Static Methods</a></li>
<li class="toctree-l3"><a class="reference internal" href="#Reading-Comprehension-Solutions">Reading Comprehension Solutions</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="Applications_of_OOP.html">Applications of Object Oriented Programming</a></li>
<li class="toctree-l2"><a class="reference internal" href="Special_Methods.html">Special Methods</a></li>
<li class="toctree-l2"><a class="reference internal" href="Inheritance.html">Inheritance</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../module_5.html">Module 5: Odds and Ends</a></li>
<li class="toctree-l1"><a class="reference internal" href="../changes.html">Changelog</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
<nav class="wy-nav-top" aria-label="top navigation">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../index.html">Python Like You Mean It</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="../index.html">Docs</a> »</li>
<li><a href="../module_4.html">Module 4: Object Oriented Programming</a> »</li>
<li>Methods</li>
<li class="wy-breadcrumbs-aside">
<a href="../_sources/Module4_OOP/Methods.md.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="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>
<div class="section" id="Methods">
<h1>Methods<a class="headerlink" href="#Methods" title="Permalink to this headline">¶</a></h1>
<p>Recall that a method is an attribute of a class that is a function. For example, “append” is a method that is defined for the <code class="docutils literal notranslate"><span class="pre">list</span></code> class and “capitalize” is a method of the <code class="docutils literal notranslate"><span class="pre">str</span></code> (string) class.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># create an instance of the `list` class/type</span>
<span class="c1"># and invoke the instance method `append`</span>
<span class="o">>>></span> <span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
<span class="o">>>></span> <span class="n">a</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="o">>>></span> <span class="n">a</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="c1"># create an instance of the `str` class/type</span>
<span class="c1"># and invoke the instance method `capitalize`</span>
<span class="o">>>></span> <span class="n">b</span> <span class="o">=</span> <span class="s2">"moo"</span>
<span class="o">>>></span> <span class="n">b</span><span class="o">.</span><span class="n">capitalize</span><span class="p">()</span>
<span class="s1">'Moo'</span>
</pre></div>
</div>
<p>Here we will encounter three varieties of methods:</p>
<ul class="simple">
<li><p>instance methods</p></li>
<li><p>class methods</p></li>
<li><p>static methods</p></li>
</ul>
<p>whose differences are relatively minor but are important to understand. The functions “append” and “capitalize” are both examples of instance methods, specifically, as they are designed to be invoked by a particular list instance and string instance, respectively.</p>
<p>We have already worked with the instance method <code class="docutils literal notranslate"><span class="pre">__init__</span></code>, which is special in that it is reserved by Python to be executed whenever class-initialization is invoked. Similarly, the special instance method <code class="docutils literal notranslate"><span class="pre">__add__</span></code> informs how an object interacts with the <code class="docutils literal notranslate"><span class="pre">+</span></code> operator. For example, <code class="docutils literal notranslate"><span class="pre">float.__add__</span></code> specifies that <code class="docutils literal notranslate"><span class="pre">+</span></code> will sum the values of <code class="docutils literal notranslate"><span class="pre">float</span></code> instances, whereas <code class="docutils literal notranslate"><span class="pre">list.__add__</span></code> specifies that <code class="docutils literal notranslate"><span class="pre">+</span></code> will concatenate <code class="docutils literal notranslate"><span class="pre">list</span></code> instances together. We will conclude our discussion of
methods by surveying a number of these special methods - they will greatly bolster our ability to define convenient, user-friendly classes.</p>
<div class="section" id="Instance-Methods">
<h2>Instance Methods<a class="headerlink" href="#Instance-Methods" title="Permalink to this headline">¶</a></h2>
<p>An <em>instance method</em> is defined whenever a function definition is specified within the body of a class. This may seem trivial but there is still a significant nuance that must be cleared up, which is that ‘<code class="docutils literal notranslate"><span class="pre">self</span></code>’ is the defacto first-argument for any instance method. This is something that we encountered when working with <code class="docutils literal notranslate"><span class="pre">__init__</span></code>. Let’s proceed naively so that we will hit a very common error, which will bring this matter to light. We begin by creating a class with an instance method that
simply accepts one argument and then returns that argument unchanged:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Dummy</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="sd">""" An instance method that returns `x` unchanged.</span>
<span class="sd"> This is a bad version of this instance method!"""</span>
<span class="k">return</span> <span class="n">x</span>
</pre></div>
</div>
<p>We can call this method from the class object <code class="docutils literal notranslate"><span class="pre">Dummy</span></code> itself, and it will behave as-expected:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">Dummy</span><span class="o">.</span><span class="n">func</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="go">2</span>
</pre></div>
</div>
<p>but something strange happens when we try to call <code class="docutils literal notranslate"><span class="pre">func</span></code> from an instance of <code class="docutils literal notranslate"><span class="pre">Dummy</span></code>:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># calling `func` from an instance of `Dummy` produces</span>
<span class="c1"># an unexpected error</span>
<span class="o">>>></span> <span class="n">inst</span> <span class="o">=</span> <span class="n">Dummy</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">inst</span><span class="o">.</span><span class="n">func</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="ne">TypeError</span><span class="p">:</span> <span class="n">func</span><span class="p">()</span> <span class="n">takes</span> <span class="mi">1</span> <span class="n">positional</span> <span class="n">argument</span> <span class="n">but</span> <span class="mi">2</span> <span class="n">were</span> <span class="n">given</span>
</pre></div>
</div>
<p>At first glance, this error message doesn’t seem to make any sense. It is indeed true that <code class="docutils literal notranslate"><span class="pre">func</span></code> only accepts one argument - we specified that it should accept the argument <code class="docutils literal notranslate"><span class="pre">x</span></code> in its function definition. How is it that <code class="docutils literal notranslate"><span class="pre">inst.func(2)</span></code> specifies <em>two</em> arguments? It seems like we are solely passing <code class="docutils literal notranslate"><span class="pre">2</span></code> to our method. Herein lies an extremely important detail:</p>
<div class="admonition warning">
<p class="admonition-title fa fa-exclamation-circle"><strong>Important!</strong></p>
<p>When you call an instance method (e.g. <code class="docutils literal notranslate"><span class="pre">func</span></code>) from an instance object (e.g. <code class="docutils literal notranslate"><span class="pre">inst</span></code>), Python automatically passes that instance object as the first argument, in addition to any other arguments that were passed in by the user.</p>
</div>
<p>So according to this, <code class="docutils literal notranslate"><span class="pre">inst</span></code> is being passed as the argument <code class="docutils literal notranslate"><span class="pre">x</span></code> and we are attempting to pass <code class="docutils literal notranslate"><span class="pre">2</span></code> as a second argument to the method; this explains the error message complaining about passing <code class="docutils literal notranslate"><span class="pre">func</span></code> two arguments. By this logic we should be able to call <code class="docutils literal notranslate"><span class="pre">a.func()</span></code> and see that <code class="docutils literal notranslate"><span class="pre">inst</span></code> is being passed as the argument <code class="docutils literal notranslate"><span class="pre">x</span></code> - recall that <code class="docutils literal notranslate"><span class="pre">func</span></code> is defined to simply return <code class="docutils literal notranslate"><span class="pre">x</span></code> unchanged. Let’s confirm this:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># verifying that `inst` is being passed as the first argument</span>
<span class="c1"># of the instance-method `func`</span>
<span class="c1"># note the memory address of the Dummy-instance `inst`</span>
<span class="o">>>></span> <span class="n">inst</span>
<span class="o"><</span><span class="n">__main__</span><span class="o">.</span><span class="n">Dummy</span> <span class="n">at</span> <span class="mh">0x284f0008da0</span><span class="o">></span>
<span class="c1"># `inst.func()` automatically receives `inst` as the</span>
<span class="c1"># input argument, which is then returned unchanged</span>
<span class="o">>>></span> <span class="n">inst</span><span class="o">.</span><span class="n">func</span><span class="p">()</span>
<span class="o"><</span><span class="n">__main__</span><span class="o">.</span><span class="n">Dummy</span> <span class="n">at</span> <span class="mh">0x284f0008da0</span><span class="o">></span>
<span class="c1"># `inst` is indeed being passed to, and</span>
<span class="c1"># returned by, `func`</span>
<span class="o">>>></span> <span class="n">out</span> <span class="o">=</span> <span class="n">inst</span><span class="o">.</span><span class="n">func</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">inst</span> <span class="ow">is</span> <span class="n">out</span>
<span class="kc">True</span>
</pre></div>
</div>
<p><em>Note that this “under the hood” behavior only occurs when the method is being called from an instance</em>; this is why we didn’t face this issue when invoking <code class="docutils literal notranslate"><span class="pre">func</span></code> from <code class="docutils literal notranslate"><span class="pre">Dummy</span></code> - <code class="docutils literal notranslate"><span class="pre">Dummy</span></code> is a class object, not an instance. Thus, <code class="docutils literal notranslate"><span class="pre">inst.func()</span></code> is equivalent to <code class="docutils literal notranslate"><span class="pre">Dummy.func(inst)</span></code>:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">out</span> <span class="o">=</span> <span class="n">Dummy</span><span class="o">.</span><span class="n">func</span><span class="p">(</span><span class="n">inst</span><span class="p">)</span>
<span class="gp">>>> </span><span class="n">out</span> <span class="ow">is</span> <span class="n">inst</span>
<span class="go">True</span>
</pre></div>
</div>
<p>In its current form, there is no way for us to pass an argument to <code class="docutils literal notranslate"><span class="pre">func</span></code> when we are calling it from an instance of <code class="docutils literal notranslate"><span class="pre">Dummy</span></code>. To solve this issue, we will refactor our definition of <code class="docutils literal notranslate"><span class="pre">func</span></code> to anticipate the passing of the instance object as the first argument.</p>
<div class="section" id="The-self-Argument">
<h3>The <code class="docutils literal notranslate"><span class="pre">self</span></code> Argument<a class="headerlink" href="#The-self-Argument" title="Permalink to this headline">¶</a></h3>
<p>We will want to define our instance methods in a way that anticipates that Python will automatically pass an instance object as the first argument. Thus if we want our method to accept <span class="math notranslate nohighlight">\(N\)</span> external argument, we should define its signature to have <span class="math notranslate nohighlight">\(N+1\)</span> arguments, with the understanding that Python will pass the instance object as the first argument. The accepted convention is to call this first argument <code class="docutils literal notranslate"><span class="pre">self</span></code>. There is no significance to this name beyond it being the
widely-adopted convention among Python users; “self” is meant to indicate that the instance object is passing itself as the first argument of the method. Consider the following example:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># demonstrate the use of `self` in instance arguments</span>
<span class="k">class</span> <span class="nc">Number</span><span class="p">:</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">value</span>
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">new_value</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">+</span> <span class="n">new_value</span>
</pre></div>
</div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># calls __init__, setting self.value = 4.0</span>
<span class="o">>>></span> <span class="n">x</span> <span class="o">=</span> <span class="n">Number</span><span class="p">(</span><span class="mf">4.0</span><span class="p">)</span>
<span class="c1"># `x` gets passed to `self`</span>
<span class="o">>>></span> <span class="n">x</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="mf">2.0</span><span class="p">)</span>
<span class="mf">6.0</span>
<span class="c1"># Calling the instance method from the class object.</span>
<span class="c1"># We must explicitly pass an object to `self`</span>
<span class="o">>>></span> <span class="n">Number</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="mf">2.0</span><span class="p">)</span>
<span class="mf">6.0</span>
</pre></div>
</div>
<p>Note the utility of having <code class="docutils literal notranslate"><span class="pre">self</span></code> be automatically passed in as an argument to both <code class="docutils literal notranslate"><span class="pre">__init__</span></code> and <code class="docutils literal notranslate"><span class="pre">add</span></code>. An instance method is meant to have access to the instance object that is calling it - when you call <code class="docutils literal notranslate"><span class="pre">capitalize</span></code> from a string instance, it is obvious that you want to capitalize <em>that</em> specific string. It would be tedious and redundant if Python did not manage that automatically.</p>
<p>Next, we will see that we can also define class-methods, which automatically have <em>class objects</em> get passed as their first arguments, and static methods, which do not have any objects passed to them under the hood.</p>
<div class="admonition note">
<p class="admonition-title fa fa-exclamation-circle"><strong>Reading Comprehension: Invoking Instance Methods</strong></p>
<p>Rewrite <code class="docutils literal notranslate"><span class="pre">Dummy</span></code> so that its instance method <code class="docutils literal notranslate"><span class="pre">func</span></code> accepts two arguments: the instance object that Python automatically passes and the argument <code class="docutils literal notranslate"><span class="pre">x</span></code>, which we want <code class="docutils literal notranslate"><span class="pre">func</span></code> to return unchanged. Create an instance of <code class="docutils literal notranslate"><span class="pre">Dummy</span></code> and call <code class="docutils literal notranslate"><span class="pre">func</span></code> from this instance and pass it the string <code class="docutils literal notranslate"><span class="pre">"hi"</span></code>, what will be returned? What will happen if you try to call <code class="docutils literal notranslate"><span class="pre">Dummy.func("hi")</span></code>? Why? How can we modify this call from <code class="docutils literal notranslate"><span class="pre">Dummy</span></code> itself so that the method will work as desired?</p>
</div>
</div>
</div>
<div class="section" id="Class-Methods">
<h2>Class Methods<a class="headerlink" href="#Class-Methods" title="Permalink to this headline">¶</a></h2>
<p>A class method is similar to an instance method, but it has a <em>class object</em> passed as its first argument. Recall that, when an instance method is called from an instance object, that instance object is automatically passed as the first argument to the method. By contrast, when a <em>class method</em> is called from a either a class object or an instance object, the class object is automatically passed as the first argument to the method. Instead of calling this first argument <code class="docutils literal notranslate"><span class="pre">self</span></code>, the convention
is to name it <code class="docutils literal notranslate"><span class="pre">cls</span></code>.</p>
<p>To define a class method you must <em>decorate</em> the method definition with a special built-in decorator <code class="docutils literal notranslate"><span class="pre">classmethod</span></code>. We have not discussed decorators. Suffice it to know that this simply “tags” the method, so that Python knows to treat it like a class method instead of an instance method. The following demonstrates this decoration process:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Dummy</span><span class="p">:</span>
<span class="nd">@classmethod</span>
<span class="k">def</span> <span class="nf">class_func</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
<span class="sd">""" A class method defined to simply</span>
<span class="sd"> return `cls` unchanged"""</span>
<span class="k">return</span> <span class="bp">cls</span>
</pre></div>
</div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># `Dummy` gets passed as `cls` automatically.</span>
<span class="c1"># We defined `class_func` to return `cls` unchanged</span>
<span class="o">>>></span> <span class="n">Dummy</span><span class="o">.</span><span class="n">class_func</span><span class="p">()</span>
<span class="n">__main__</span><span class="o">.</span><span class="n">Dummy</span>
<span class="c1"># `Dummy.class_func()` returns `Dummy`</span>
<span class="o">>>></span> <span class="n">out</span> <span class="o">=</span> <span class="n">Dummy</span><span class="o">.</span><span class="n">class_func</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">out</span> <span class="ow">is</span> <span class="n">Dummy</span>
<span class="kc">True</span>
<span class="c1"># `Dummy` gets passed as `cls` automatically</span>
<span class="c1"># even when `class_func` is called from an instance</span>
<span class="o">>>></span> <span class="n">inst</span> <span class="o">=</span> <span class="n">Dummy</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">inst</span><span class="o">.</span><span class="n">class_func</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">inst</span><span class="o">.</span><span class="n">class_func</span><span class="p">()</span>
<span class="n">__main__</span><span class="o">.</span><span class="n">Dummy</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">dict.fromkeys</span></code> is an example of a class method that takes in an iterable, and returns a dictionary whose keys are the elements of that iterable, and whose values all default to <code class="docutils literal notranslate"><span class="pre">None</span></code>.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nb">dict</span><span class="o">.</span><span class="n">fromkeys</span><span class="p">(</span><span class="s2">"abcd"</span><span class="p">,</span> <span class="mf">2.3</span><span class="p">)</span>
<span class="go">{'a': 2.3, 'b': 2.3, 'c': 2.3, 'd': 2.3}</span>
</pre></div>
</div>
<p>It is sensible that this is a class method rather than an instance method, as the method creates a brand new dictionary from scratch. It need only have access to the <code class="docutils literal notranslate"><span class="pre">dict</span></code> object (i.e. the <code class="docutils literal notranslate"><span class="pre">cls</span></code> argument) so that it can construct the dictionary. The following is what an implementation of <code class="docutils literal notranslate"><span class="pre">fromkeys</span></code> could look like, were we to define <code class="docutils literal notranslate"><span class="pre">dict</span></code> ourselves:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">dict</span><span class="p">:</span>
<span class="c1"># assume all other dictionary methods are defined here</span>
<span class="nd">@classmethod</span>
<span class="k">def</span> <span class="nf">fromkeys</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">iterable</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="sd">""" Creates a dictionary whose keys are the elements of `iterable`. All</span>
<span class="sd"> keys map to `value`.</span>
<span class="sd"> Parameters</span>
<span class="sd"> ----------</span>
<span class="sd"> iterable: Iterable[Hashable]</span>
<span class="sd"> An iterable of valid dictionary keys (i.e. any object that is hashable).</span>
<span class="sd"> value : Optional[Any]</span>
<span class="sd"> The value that all of the keys will map to. Defaults to `None`.</span>
<span class="sd"> Returns</span>
<span class="sd"> -------</span>
<span class="sd"> dict """</span>
<span class="n">new_dict</span> <span class="o">=</span> <span class="bp">cls</span><span class="p">()</span> <span class="c1"># equivalent to `dict()`: creates a new dictionary instance</span>
<span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">iterable</span><span class="p">:</span>
<span class="n">new_dict</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
<span class="k">return</span> <span class="n">new_dict</span>
</pre></div>
</div>
</div>
<div class="section" id="Static-Methods">
<h2>Static Methods<a class="headerlink" href="#Static-Methods" title="Permalink to this headline">¶</a></h2>
<p>A static method is simply a method whose arguments must all be passed explicitly by the user. That is, Python doesn’t pass anything to a static method automatically. The built-in decorator <code class="docutils literal notranslate"><span class="pre">staticmethod</span></code> is used to distinguish a method as being static rather than an instance method.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Dummy</span><span class="p">:</span>
<span class="nd">@staticmethod</span>
<span class="k">def</span> <span class="nf">static_func</span><span class="p">():</span>
<span class="sd">""" A static method defined to always returns</span>
<span class="sd"> the string `'hi'`"""</span>
<span class="k">return</span> <span class="s1">'hi'</span>
</pre></div>
</div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># A static method can be called from a class object</span>
<span class="c1"># or an instance object; nothing gets passed to it</span>
<span class="c1"># automatically.</span>
<span class="o">>>></span> <span class="n">Dummy</span><span class="o">.</span><span class="n">static_func</span><span class="p">()</span>
<span class="s1">'hi'</span>
<span class="o">>>></span> <span class="n">inst</span> <span class="o">=</span> <span class="n">Dummy</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">inst</span><span class="o">.</span><span class="n">static_func</span><span class="p">()</span>
<span class="s1">'hi'</span>
</pre></div>
</div>
</div>
<div class="section" id="Reading-Comprehension-Solutions">
<h2>Reading Comprehension Solutions<a class="headerlink" href="#Reading-Comprehension-Solutions" title="Permalink to this headline">¶</a></h2>
<p><strong>Invoking Instance Methods: Solution</strong></p>
<p>Rewrite <code class="docutils literal notranslate"><span class="pre">Dummy</span></code> so that its instance method <code class="docutils literal notranslate"><span class="pre">func</span></code> accepts two arguments: the instance object that Python automatically passes and the argument <code class="docutils literal notranslate"><span class="pre">x</span></code>, which we want <code class="docutils literal notranslate"><span class="pre">func</span></code> to return unchanged.</p>
<blockquote>
<div><p>We will rewite func to accept an argument called ‘self’, which will accept the instance object that is passed “under the hood” , and ‘x’. As you will see in the reading, the name argument ‘self’ is simply used by convention.</p>
</div></blockquote>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Dummy</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
<span class="k">return</span> <span class="n">x</span>
</pre></div>
</div>
<p>Create an instance of <code class="docutils literal notranslate"><span class="pre">Dummy</span></code> and call <code class="docutils literal notranslate"><span class="pre">func</span></code> from this instance and pass it the string <code class="docutils literal notranslate"><span class="pre">"hi"</span></code>.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">inst</span> <span class="o">=</span> <span class="n">Dummy</span><span class="p">()</span>
<span class="gp">>>> </span><span class="n">inst</span><span class="o">.</span><span class="n">func</span><span class="p">(</span><span class="s2">"hi"</span><span class="p">)</span> <span class="c1"># `inst` is passed to the argument `self`</span>
<span class="go">'hi'</span>
</pre></div>
</div>
<p>What will happen if you try to call <code class="docutils literal notranslate"><span class="pre">Dummy.func("hi")</span></code>? Why?</p>
<blockquote>
<div><p>This will raise an error, which complains that func expects two arguments, and that we have only passed it one. Indeed, we will have only passed it the object “hi” and nothing else. Dummy is a class object, not an instance object. Thus Python does not do anything special “under the hood” when we call Dummy.func. We must pass something to the self argument. Because this particular method doesn’t do anything with self, we can just pass it None, or any other object, really.</p>
</div></blockquote>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># Dummy.func("hi") would raise an error</span>
<span class="o">>>></span> <span class="n">Dummy</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="s2">"hi"</span><span class="p">)</span>
<span class="s1">'hi'</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<footer>
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
<a href="Applications_of_OOP.html" class="btn btn-neutral float-right" title="Applications of Object Oriented Programming" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right"></span></a>
<a href="Brief_Review.html" class="btn btn-neutral float-left" title="A Brief Summary of Terms and Concepts" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left"></span> Previous</a>
</div>
<hr/>
<div role="contentinfo">
<p>
© Copyright 2019, Ryan Soklaski
</p>
</div>
Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script type="text/javascript">
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>