1
1
.. include :: include.rst
2
2
3
- **************************************************************************
3
+ ****************************************************
4
4
Session Eight: More OO: Properties, Special methods.
5
- **************************************************************************
5
+ ****************************************************
6
6
7
7
8
8
================
@@ -27,8 +27,6 @@ Lightning Talks Today:
27
27
28
28
Paul Briant
29
29
30
- Brandon Chavis
31
-
32
30
Jay Raina
33
31
34
32
Josh Hicks
@@ -48,7 +46,7 @@ The bulk of the homework for the rest of the class will be a personal project:
48
46
* I don't require any specific python features (i.e. classes): use
49
47
what is appropriate for your project
50
48
51
- * Due the Friday after the last class (December 11)
49
+ * Due the Sunday after the last class (December 11)
52
50
53
51
|
54
52
| By next week, send me a project proposal: short and sweet.
@@ -75,10 +73,164 @@ And there is no need to check if it's empty before trying to loop through it.
75
73
76
74
no need for ``!= {} `` -- an empty dict is "Falsey"
77
75
78
- **but ** no need for that check at all. If the dict (or ist , or tuple) is
76
+ **but ** no need for that check at all. If the dict (or list , or tuple) is
79
77
empty, then the loop is a do-nothing operation:
80
78
81
- * notes on Duck Typing: :ref: `exercise_html_renderer ` and code review
79
+ .. code-block :: python
80
+
81
+ for key, value in self .attributes.items():
82
+ self .atts += ' {} ="{} "' .format(key, value)
83
+
84
+ will not run if self.attributes is an empty dict.
85
+
86
+
87
+ Dynamic typing and class attributes
88
+ -----------------------------------
89
+
90
+ * what happens if we change a class attribute after creating instances??
91
+
92
+ - let's try ``Element.indent `` ...
93
+
94
+ * setting an instance attribute overwrites class attributes:
95
+
96
+ ``self.tag = `` overrights the class attribute (sort of!)
97
+
98
+ Let's experiment with that.
99
+
100
+
101
+ dict as switch
102
+ --------------
103
+
104
+ .. rst-class :: medium
105
+
106
+ What to use instead of "switch-case"?
107
+
108
+ A number of languages have a "switch-case" construct::
109
+
110
+ switch(argument) {
111
+ case 0:
112
+ return "zero";
113
+ case 1:
114
+ return "one";
115
+ case 2:
116
+ return "two";
117
+ default:
118
+ return "nothing";
119
+ };
120
+
121
+ How do you spell this in python?
122
+
123
+ ``if-elif `` chains
124
+ -------------------
125
+
126
+ The obvious way to spell it is a chain of ``elif `` statements:
127
+
128
+ .. code-block :: python
129
+
130
+ if argument == 0 :
131
+ return " zero"
132
+ elif argument == 1 :
133
+ return " one"
134
+ elif argument == 2 :
135
+ return " two"
136
+ else :
137
+ return " nothing"
138
+
139
+ And there is nothing wrong with that, but....
140
+
141
+ .. nextslide ::
142
+
143
+ The ``elif `` chain is neither elegant nor efficient.
144
+
145
+ There are a number of ways to spell it in python -- one elegant one is to use a dict:
146
+
147
+ .. code-block :: python
148
+
149
+ arg_dict = {0 :" zero" , 1 :" one" , 2 : " two" }
150
+ dict .get(argument, " nothing" )
151
+
152
+ Simple, elegant, and fast.
153
+
154
+ You can do a dispatch table by putting functions as the value.
155
+
156
+ Example: Chris' mailroom2 solution.
157
+
158
+ Polymorphism as switch:
159
+ -----------------------
160
+
161
+ It turns out that a lot of uses of switch-case in non-OO languages is to
162
+ change behaviour depending on teh type of object being worked on::
163
+
164
+ switch(object.tag) {
165
+ case 'html':
166
+ render_html_element;
167
+ case 'p':
168
+ render_p_element;
169
+ ...
170
+
171
+ I saw some of this in the html renderer:
172
+
173
+ .. nextslide ::
174
+
175
+ .. code-block :: python
176
+
177
+ def render (out_file , ind = " " ):
178
+ ... .
179
+ if self .tag == ' html' :
180
+ tag = " <html>"
181
+ end_tag = " </html>"
182
+ elif self .tag == ' p' :
183
+ tag = " <p>"
184
+ end_tag = " </p>"
185
+
186
+ This will work, of course, but:
187
+
188
+ * it means you need to know every tag that you might render when you write this render method.
189
+
190
+ * In a more complex system, you will need to go update all sorts of things all over teh place when you add a tag.
191
+
192
+ * It means anyone extending the system with more tags needs to edit the core base class.
193
+
194
+ Polymorphism
195
+ ------------
196
+
197
+ The alternative is to use polymorphism:
198
+
199
+ Your ``render() `` method doesn't need to know what all the objects are
200
+ that it may need to render.
201
+
202
+ All it needs to know is that they all will have a method
203
+ that does the right thing.
204
+
205
+ So the above becomes, simply:
206
+
207
+ .. code-block :: python
208
+
209
+ def render (out_file , ind = " " ):
210
+ ... .
211
+ tag, end_tag = self .make_tags()
212
+
213
+ This is known as polymorphism, because many different objects are behave
214
+ the same way.
215
+
216
+ .. nextslide ::
217
+
218
+ This is usally handled by subclassing, so they all get all teh same
219
+ methods by default, and you only need to specialize the ones that need it.
220
+
221
+ But in Python -- it can be done with duck-typing instead, as the TextWrapper example.
222
+
223
+ Duck typing and EAFP
224
+ --------------------
225
+
226
+ * notes on Duck Typing: :ref: `exercise_html_renderer `
227
+
228
+ * put the ``except `` as close as you can to where you expect an exception to be raised!
229
+
230
+ * Let's look at a couple ways to do that.
231
+
232
+ Code Review
233
+ -----------
82
234
83
235
* anyone stuck that wants to work through your code?
84
236
@@ -90,10 +242,12 @@ Lightning Talks:
90
242
.. rst-class :: medium
91
243
92
244
|
93
- | Paul Briant
245
+ | Paul Briant
94
246
|
95
- | Brandon Chavis
247
+ | Jay Raina
96
248
|
249
+ | Josh Hicks
250
+
97
251
98
252
99
253
==========
@@ -261,17 +415,6 @@ For now, Let's do steps 1-4 of:
261
415
262
416
:ref: `exercise_circle_class `
263
417
264
- Lightning talks:
265
- -----------------
266
-
267
- .. rst-class :: medium
268
-
269
- |
270
- | Jay N Raina
271
- |
272
- | Josh Hicks
273
- |
274
-
275
418
276
419
========================
277
420
Static and Class Methods
@@ -289,7 +432,6 @@ Static and Class Methods
289
432
And you've seen how you can call *unbound * methods on a class object so
290
433
long as you pass an instance of that class as the first argument.
291
434
292
- |
293
435
294
436
.. rst-class :: centered
295
437
0 commit comments