forked from yasoob/intermediatePython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclasses.html
More file actions
240 lines (209 loc) · 15 KB
/
classes.html
File metadata and controls
240 lines (209 loc) · 15 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
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Classes</title>
<link rel="stylesheet" href="_static/epub.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
</head>
<body role="document">
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="nav-item nav-item-0"><a href="index.html">Python Tips 0.1 documentation</a> »</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="body" role="main">
<div class="section" id="classes">
<h1>Classes</h1>
<p>Classes are the core of Python. They give us a lot of power but it is
really easy to misuse this power. In this section I will share some
obscure tricks and caveats related to <code class="docutils literal"><span class="pre">classes</span></code> in Python. Let’s get
going!</p>
<div class="section" id="instance-class-variables">
<h2>1. Instance & Class variables</h2>
<p>Most beginners and even some advance Python programmers do not
understand the distinction between instance and class variables. Their
lack of understanding forces them to use these different types of
variables incorrectly. Let’s understand them.</p>
<p>The basic difference is:</p>
<ul class="simple">
<li>Instance variables are for data which is unique to every object</li>
<li>Class variables are for data shared between different instances of a
class</li>
</ul>
<p>Let’s take a look at an example:</p>
<div class="code python highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">Cal</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="c"># pi is a class variable</span>
<span class="n">pi</span> <span class="o">=</span> <span class="mf">3.142</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">radius</span><span class="p">):</span>
<span class="c"># self.radius is an instance variable</span>
<span class="bp">self</span><span class="o">.</span><span class="n">radius</span> <span class="o">=</span> <span class="n">radius</span>
<span class="k">def</span> <span class="nf">area</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">pi</span> <span class="o">*</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">radius</span> <span class="o">**</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">Cal</span><span class="p">(</span><span class="mi">32</span><span class="p">)</span>
<span class="n">a</span><span class="o">.</span><span class="n">area</span><span class="p">()</span>
<span class="c"># Output: 3217.408</span>
<span class="n">a</span><span class="o">.</span><span class="n">pi</span>
<span class="c"># Output: 3.142</span>
<span class="n">a</span><span class="o">.</span><span class="n">pi</span> <span class="o">=</span> <span class="mi">43</span>
<span class="n">a</span><span class="o">.</span><span class="n">pi</span>
<span class="c"># Output: 43</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">Cal</span><span class="p">(</span><span class="mi">44</span><span class="p">)</span>
<span class="n">b</span><span class="o">.</span><span class="n">area</span><span class="p">()</span>
<span class="c"># Output: 6082.912</span>
<span class="n">b</span><span class="o">.</span><span class="n">pi</span>
<span class="c"># Output: 3.142</span>
<span class="n">b</span><span class="o">.</span><span class="n">pi</span> <span class="o">=</span> <span class="mi">50</span>
<span class="n">b</span><span class="o">.</span><span class="n">pi</span>
<span class="c"># Output: 50</span>
</pre></div>
</div>
<p>There are not much issues while using mutable class variables. This is
the major reason due to which beginners do not try to learn more about
this subject because everything works! If you also believe that instance
and class variables can not cause any problem if used incorrectly then
check the next example.</p>
<div class="code python highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">SuperClass</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="n">superpowers</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
<span class="k">def</span> <span class="nf">add_superpower</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">power</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">superpowers</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">power</span><span class="p">)</span>
<span class="n">foo</span> <span class="o">=</span> <span class="n">SuperClass</span><span class="p">(</span><span class="s">'foo'</span><span class="p">)</span>
<span class="n">bar</span> <span class="o">=</span> <span class="n">SuperClass</span><span class="p">(</span><span class="s">'bar'</span><span class="p">)</span>
<span class="n">foo</span><span class="o">.</span><span class="n">name</span>
<span class="c"># Output: 'foo'</span>
<span class="n">bar</span><span class="o">.</span><span class="n">name</span>
<span class="c"># Output: 'bar'</span>
<span class="n">foo</span><span class="o">.</span><span class="n">add_superpower</span><span class="p">(</span><span class="s">'fly'</span><span class="p">)</span>
<span class="n">bar</span><span class="o">.</span><span class="n">superpowers</span>
<span class="c"># Output: ['fly']</span>
<span class="n">foo</span><span class="o">.</span><span class="n">superpowers</span>
<span class="c"># Output: ['fly']</span>
</pre></div>
</div>
<p>That is the beauty of the wrong usage of mutable class variables. To
make your code safe against this kind of surprize attacks then make sure
that you do not use mutable class variables. You may use them only if
you know what you are doing.</p>
</div>
<div class="section" id="new-style-classes">
<h2>2.New style classes:</h2>
<p>New style classes were introduced in Python 2.1 but a lot of people do
not know about them even now! It is so because Python also supports old
style classes just to maintain backward compatibility. I have said a lot
about new and old but I have not told you about the difference. Well the
major difference is that:</p>
<ul class="simple">
<li>Old base classes do not inherit from anything</li>
<li>New style base classes inherit from <code class="docutils literal"><span class="pre">object</span></code></li>
</ul>
<p>A very basic example is:</p>
<div class="code python highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">OldClass</span><span class="p">():</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'I am an old class'</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">NewClass</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'I am a jazzy new class'</span><span class="p">)</span>
<span class="n">old</span> <span class="o">=</span> <span class="n">OldClass</span><span class="p">()</span>
<span class="c"># Output: I am an old class</span>
<span class="n">new</span> <span class="o">=</span> <span class="n">NewClass</span><span class="p">()</span>
<span class="c"># Output: I am a jazzy new class</span>
</pre></div>
</div>
<p>This inheritance from <code class="docutils literal"><span class="pre">object</span></code> allows new style classes to utilize
some <em>magic</em>. A major advantage is that you can employ some useful
optimizations like <code class="docutils literal"><span class="pre">__slots__</span></code>. You can use <code class="docutils literal"><span class="pre">super()</span></code> and
descriptors and the likes. Bottom line? Always try to use new-style
classes.</p>
<p><strong>Note:</strong> Python 3 only has new-style classes. It does not matter
whether you subclass from <code class="docutils literal"><span class="pre">object</span></code> or not. However it is recommended
that you still subclass from <code class="docutils literal"><span class="pre">object</span></code>.</p>
</div>
<div class="section" id="magic-methods">
<h2>3.Magic Methods:</h2>
<p>Python’s classes are famous for their magic methods, commonly called
<strong>dunder</strong> methods. I am going to discuss a few of them.</p>
<ul class="simple">
<li><code class="docutils literal"><span class="pre">__init__</span></code></li>
</ul>
<p>It is a class innitializer. Whenever an instance of a class is created
it’s <code class="docutils literal"><span class="pre">__init__</span></code> method. For instance:</p>
<div class="code python highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">GetTest</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Greetings!!'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">another_method</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'I am another method which is not'</span>
<span class="s">' automatically called'</span><span class="p">)</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">GetTest</span><span class="p">()</span>
<span class="c"># Output: Greetings!!</span>
<span class="n">a</span><span class="o">.</span><span class="n">another_method</span><span class="p">()</span>
<span class="c"># Output: I am another method which is not automatically</span>
<span class="c"># called</span>
</pre></div>
</div>
<p>You can see that <code class="docutils literal"><span class="pre">__init__</span></code> is called immediately after an instance is
created. You can also pass arguments to the class during it’s
innitialization. Like this:</p>
<div class="code python highlight-python"><div class="highlight"><pre>class GetTest(object):
def __init__(self, name):
print('Greetings!! {0}'.format(name))
def another_method(self):
print('I am another method which is not'
' automatically called')
a = GetTest('yasoob')
# Output: Greetings!! yasoob
# Try creating an instance without the name arguments
b = GetTest()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() takes exactly 2 arguments (1 given)
</pre></div>
</div>
<p>I am sure that now you understand the <code class="docutils literal"><span class="pre">__init__</span></code> method.</p>
<ul class="simple">
<li><code class="docutils literal"><span class="pre">__getitem__</span></code></li>
</ul>
<p>Implementing <strong>getitem</strong> in a class allows its instances to use the []
(indexer) operator. Here is an example:</p>
<div class="code python highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">GetTest</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">info</span> <span class="o">=</span> <span class="p">{</span>
<span class="s">'name'</span><span class="p">:</span><span class="s">'Yasoob'</span><span class="p">,</span>
<span class="s">'country'</span><span class="p">:</span><span class="s">'Pakistan'</span><span class="p">,</span>
<span class="s">'number'</span><span class="p">:</span><span class="mi">12345812</span>
<span class="p">}</span>
<span class="k">def</span> <span class="nf">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span><span class="n">i</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">info</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
<span class="n">foo</span> <span class="o">=</span> <span class="n">OldClass</span><span class="p">()</span>
<span class="n">foo</span><span class="p">[</span><span class="s">'title'</span><span class="p">]</span>
<span class="c"># Output: 'Yasoob'</span>
<span class="n">foo</span><span class="p">[</span><span class="s">'number'</span><span class="p">]</span>
<span class="c"># Output: 36845124</span>
</pre></div>
</div>
<p>Without the <code class="docutils literal"><span class="pre">__getitem__</span></code> method we would have got this error:</p>
<div class="code python highlight-python"><div class="highlight"><pre><span class="gp">>>> </span><span class="n">foo</span><span class="p">[</span><span class="s">'title'</span><span class="p">]</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
<span class="gr">TypeError</span>: <span class="n">'GetTest' object has no attribute '__getitem__'</span>
</pre></div>
</div>
</div>
<div class="section" id="static-class-abstract-methods">
<h2>Static, Class & Abstract methods</h2>
</div>
</div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer" role="contentinfo">
© Copyright 2015, Muhammad Yasoob Ullah Khalid.
</div>
</body>
</html>