Skip to content

Commit fe4e25a

Browse files
committed
Iterable duck types
1 parent a6658ba commit fe4e25a

File tree

4 files changed

+82
-48
lines changed

4 files changed

+82
-48
lines changed

README.md

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,8 +1172,8 @@ Iterable Duck Types
11721172
-------------------
11731173

11741174
### Iterable
1175-
* **Only required method for iterable is iter(), that should return an iterator of its contents.**
1176-
* **Contains() is automatically generated whenever iter() is present.**
1175+
* **Only required method for iterable is iter(). It should return an iterator of its contents.**
1176+
* **Contains() automatically works on any object that has iter() defined.**
11771177
```python
11781178
class MyIterable:
11791179
def __init__(self, a):
@@ -1192,58 +1192,69 @@ True
11921192
```
11931193

11941194
### Collection
1195-
* **Every collection is also an iterable.**
1195+
* **Only required methods are iter() and len().**
11961196
* **This cheatsheet actually means `'<iterable>'` when it uses `'<collection>'`.**
11971197
* **I chose not to use the name iterable because it sounds scarier and more vague than collection.**
11981198
```python
11991199
class MyCollection:
12001200
def __init__(self, a):
12011201
self.a = a
1202+
def __iter__(self):
1203+
for el in self.a:
1204+
yield el
12021205
def __contains__(self, el):
12031206
return el in self.a
12041207
def __len__(self):
12051208
return len(self.a)
1206-
def __iter__(self):
1207-
for el in self.a:
1208-
yield el
12091209
```
12101210

12111211
### Sequence
1212-
* **Every sequence is also a collection.**
1213-
* **Iter() and reversed() are automatically generated whenever getitem() is present.**
1212+
* **Only required methods are len() and getitem().**
1213+
* **Iter(), contains() and reversed() automatically work on any object that has getitem() defined.**
12141214
```python
12151215
class MySequence:
12161216
def __init__(self, a):
12171217
self.a = a
1218-
def __getitem__(self, i):
1219-
return self.a[i]
1218+
def __iter__(self):
1219+
for el in self.a:
1220+
yield el
1221+
def __contains__(self, el):
1222+
return el in self.a
12201223
def __len__(self):
12211224
return len(self.a)
1225+
def __getitem__(self, i):
1226+
return self.a[i]
1227+
def __reversed__(self):
1228+
return reversed(self.a)
12221229
```
12231230

12241231
### Collections.abc.Sequence
12251232
* **It's a richer interface than the basic sequence.**
1226-
* **Extending it generates contains(), iter(), reversed(), index(), and count().**
1233+
* **Extending it generates iter(), contains(), reversed(), index(), and count().**
12271234
* **Unlike `'abc.Iterable'` and `'abc.Collection'`, it is not a duck type. That's why `'issubclass(MySequence, collections.abc.Sequence)'` would return 'False' even if it had all the methods defined.**
12281235
```python
12291236
class MyAbcSequence(collections.abc.Sequence):
12301237
def __init__(self, a):
12311238
self.a = a
1232-
def __getitem__(self, i):
1233-
return self.a[i]
12341239
def __len__(self):
12351240
return len(self.a)
1241+
def __getitem__(self, i):
1242+
return self.a[i]
12361243
```
12371244

1238-
#### Table of the methods that each (duck) type provides:
1245+
#### Table of the required and available methods:
12391246
```text
12401247
+------------+----------+------------+----------+--------------+
12411248
| | Iterable | Collection | Sequence | abc.Sequence |
12421249
+------------+----------+------------+----------+--------------+
1243-
| iter() | yes | yes | yes | yes |
1244-
| len() | | yes | yes | yes |
1245-
| getitem() | | | yes | yes |
1246-
| contains() | | yes | | yes |
1250+
| iter() | REQ | REQ | yes | yes |
1251+
| contains() | yes | yes | yes | yes |
1252+
| len() | | REQ | REQ | REQ |
1253+
| getitem() | | | REQ | REQ |
1254+
| reversed() | | | yes | yes |
1255+
| reverse() | | | | yes |
1256+
| index() | | | | yes |
1257+
| count() | | | | yes |
12471258
+------------+----------+------------+----------+--------------+
12481259
```
12491260

index.html

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,8 +1087,8 @@ <h4 id="reusablecontextmanagers">Reusable context managers:</h4>
10871087
<h2 id="iterableducktypes"><a href="#iterableducktypes" name="iterableducktypes">#</a>Iterable Duck Types</h2>
10881088
<h3 id="iterable">Iterable</h3>
10891089
<ul>
1090-
<li><strong>Only required method for iterable is iter(), that should return an iterator of its contents.</strong></li>
1091-
<li><strong>Contains() is automatically generated whenever iter() is present.</strong></li>
1090+
<li><strong>Only required method for iterable is iter(). It should return an iterator of its contents.</strong></li>
1091+
<li><strong>Contains() automatically works on any object that has iter() defined.</strong></li>
10921092
</ul>
10931093
<pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyIterable</span>:</span>
10941094
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, a)</span>:</span>
@@ -1105,56 +1105,67 @@ <h3 id="iterable">Iterable</h3>
11051105
</code></pre>
11061106
<h3 id="collection">Collection</h3>
11071107
<ul>
1108-
<li><strong>Every collection is also an iterable.</strong></li>
1108+
<li><strong>Only required methods are iter() and len().</strong></li>
11091109
<li><strong>This cheatsheet actually means <code class="python hljs"><span class="hljs-string">'&lt;iterable&gt;'</span></code> when it uses <code class="python hljs"><span class="hljs-string">'&lt;collection&gt;'</span></code>.</strong></li>
11101110
<li><strong>I chose not to use the name iterable because it sounds scarier and more vague than collection.</strong></li>
11111111
</ul>
11121112
<pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyCollection</span>:</span>
11131113
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, a)</span>:</span>
11141114
self.a = a
1115+
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__iter__</span><span class="hljs-params">(self)</span>:</span>
1116+
<span class="hljs-keyword">for</span> el <span class="hljs-keyword">in</span> self.a:
1117+
<span class="hljs-keyword">yield</span> el
11151118
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__contains__</span><span class="hljs-params">(self, el)</span>:</span>
11161119
<span class="hljs-keyword">return</span> el <span class="hljs-keyword">in</span> self.a
11171120
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__len__</span><span class="hljs-params">(self)</span>:</span>
11181121
<span class="hljs-keyword">return</span> len(self.a)
1119-
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__iter__</span><span class="hljs-params">(self)</span>:</span>
1120-
<span class="hljs-keyword">for</span> el <span class="hljs-keyword">in</span> self.a:
1121-
<span class="hljs-keyword">yield</span> el
11221122
</code></pre>
11231123
<h3 id="sequence">Sequence</h3>
11241124
<ul>
1125-
<li><strong>Every sequence is also a collection.</strong></li>
1126-
<li><strong>Iter() and reversed() are automatically generated whenever getitem() is present.</strong></li>
1125+
<li><strong>Only required methods are len() and getitem().</strong></li>
1126+
<li><strong>Iter(), contains() and reversed() automatically work on any object that has getitem() defined.</strong></li>
11271127
</ul>
11281128
<pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MySequence</span>:</span>
11291129
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, a)</span>:</span>
11301130
self.a = a
1131-
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__getitem__</span><span class="hljs-params">(self, i)</span>:</span>
1132-
<span class="hljs-keyword">return</span> self.a[i]
1131+
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__iter__</span><span class="hljs-params">(self)</span>:</span>
1132+
<span class="hljs-keyword">for</span> el <span class="hljs-keyword">in</span> self.a:
1133+
<span class="hljs-keyword">yield</span> el
1134+
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__contains__</span><span class="hljs-params">(self, el)</span>:</span>
1135+
<span class="hljs-keyword">return</span> el <span class="hljs-keyword">in</span> self.a
11331136
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__len__</span><span class="hljs-params">(self)</span>:</span>
11341137
<span class="hljs-keyword">return</span> len(self.a)
1138+
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__getitem__</span><span class="hljs-params">(self, i)</span>:</span>
1139+
<span class="hljs-keyword">return</span> self.a[i]
1140+
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__reversed__</span><span class="hljs-params">(self)</span>:</span>
1141+
<span class="hljs-keyword">return</span> reversed(self.a)
11351142
</code></pre>
11361143
<h3 id="collectionsabcsequence">Collections.abc.Sequence</h3>
11371144
<ul>
11381145
<li><strong>It's a richer interface than the basic sequence.</strong></li>
1139-
<li><strong>Extending it generates contains(), iter(), reversed(), index(), and count().</strong></li>
1146+
<li><strong>Extending it generates iter(), contains(), reversed(), index(), and count().</strong></li>
11401147
<li><strong>Unlike <code class="python hljs"><span class="hljs-string">'abc.Iterable'</span></code> and <code class="python hljs"><span class="hljs-string">'abc.Collection'</span></code>, it is not a duck type. That's why <code class="python hljs"><span class="hljs-string">'issubclass(MySequence, collections.abc.Sequence)'</span></code> would return 'False' even if it had all the methods defined.</strong></li>
11411148
</ul>
11421149
<pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyAbcSequence</span><span class="hljs-params">(collections.abc.Sequence)</span>:</span>
11431150
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, a)</span>:</span>
11441151
self.a = a
1145-
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__getitem__</span><span class="hljs-params">(self, i)</span>:</span>
1146-
<span class="hljs-keyword">return</span> self.a[i]
11471152
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__len__</span><span class="hljs-params">(self)</span>:</span>
11481153
<span class="hljs-keyword">return</span> len(self.a)
1154+
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__getitem__</span><span class="hljs-params">(self, i)</span>:</span>
1155+
<span class="hljs-keyword">return</span> self.a[i]
11491156
</code></pre>
1150-
<h4 id="tableofthemethodsthateachducktypeprovides">Table of the methods that each (duck) type provides:</h4>
1157+
<h4 id="tableoftherequiredandavailablemethods">Table of the required and available methods:</h4>
11511158
<pre><code class="text language-text">┏━━━━━━━━━━━━┯━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━┯━━━━━━━━━━━━━━┓
11521159
┃ │ Iterable │ Collection │ Sequence │ abc.Sequence ┃
11531160
┠────────────┼──────────┼────────────┼──────────┼──────────────┨
1154-
┃ iter() │ ✓ │ ✓ │ ✓ │ ✓ ┃
1155-
┃ len() │ │ ✓ │ ✓ │ ✓ ┃
1156-
┃ getitem() │ │ + │ ✓ │ ✓ ┃
1157-
┃ contains() │ │ ✓ │ │ ✓ ┃
1161+
┃ iter() │ ! │ ! │ ✓ │ ✓ ┃
1162+
┃ contains() │ ✓ │ ✓ │ ✓ │ ✓ ┃
1163+
┃ len() │ │ ! │ ! │ ! ┃
1164+
┃ getitem() │ │ │ ! │ ! ┃
1165+
┃ reversed() │ │ │ ✓ │ ✓ ┃
1166+
┃ reverse() │ │ │ │ ✓ ┃
1167+
┃ index() │ │ │ │ ✓ ┃
1168+
┃ count() │ │ │ │ ✓ ┃
11581169
┗━━━━━━━━━━━━┷━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━┷━━━━━━━━━━━━━━┛
11591170
</code></pre>
11601171
<h2 id="enum"><a href="#enum" name="enum">#</a>Enum</h2>

parse.js

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -172,20 +172,28 @@ const DIAGRAM_7_A =
172172
'+------------+----------+------------+----------+--------------+\n' +
173173
'| | Iterable | Collection | Sequence | abc.Sequence |\n' +
174174
'+------------+----------+------------+----------+--------------+\n' +
175-
'| iter() | yes | yes | yes | yes |\n' +
176-
'| len() | | yes | yes | yes |\n' +
177-
'| getitem() | | | yes | yes |\n' +
178-
'| contains() | | yes | | yes |\n' +
175+
'| iter() | REQ | REQ | yes | yes |\n' +
176+
'| contains() | yes | yes | yes | yes |\n' +
177+
'| len() | | REQ | REQ | REQ |\n' +
178+
'| getitem() | | | REQ | REQ |\n' +
179+
'| reversed() | | | yes | yes |\n' +
180+
'| reverse() | | | | yes |\n' +
181+
'| index() | | | | yes |\n' +
182+
'| count() | | | | yes |\n' +
179183
'+------------+----------+------------+----------+--------------+\n';
180184

181185
const DIAGRAM_7_B =
182186
'┏━━━━━━━━━━━━┯━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━┯━━━━━━━━━━━━━━┓\n' +
183187
'┃ │ Iterable │ Collection │ Sequence │ abc.Sequence ┃\n' +
184188
'┠────────────┼──────────┼────────────┼──────────┼──────────────┨\n' +
185-
'┃ iter() │ ✓ │ ✓ │ ✓ │ ✓ ┃\n' +
186-
'┃ len() │ │ ✓ │ ✓ │ ✓ ┃\n' +
187-
'┃ getitem() │ │ + │ ✓ │ ✓ ┃\n' +
188-
'┃ contains() │ │ ✓ │ │ ✓ ┃\n' +
189+
'┃ iter() │ ! │ ! │ ✓ │ ✓ ┃\n' +
190+
'┃ contains() │ ✓ │ ✓ │ ✓ │ ✓ ┃\n' +
191+
'┃ len() │ │ ! │ ! │ ! ┃\n' +
192+
'┃ getitem() │ │ │ ! │ ! ┃\n' +
193+
'┃ reversed() │ │ │ ✓ │ ✓ ┃\n' +
194+
'┃ reverse() │ │ │ │ ✓ ┃\n' +
195+
'┃ index() │ │ │ │ ✓ ┃\n' +
196+
'┃ count() │ │ │ │ ✓ ┃\n' +
189197
'┗━━━━━━━━━━━━┷━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━┷━━━━━━━━━━━━━━┛\n';
190198

191199

web/script_2.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,14 @@ const DIAGRAM_7_A =
140140
'+------------+----------+------------+----------+--------------+\n' +
141141
'| | Iterable | Collection | Sequence | abc.Sequence |\n' +
142142
'+------------+----------+------------+----------+--------------+\n' +
143-
'| iter() | yes | yes | yes | yes |\n' +
144-
'| len() | | yes | yes | yes |\n' +
145-
'| getitem() | | | yes | yes |\n' +
146-
'| contains() | | yes | | yes |\n' +
143+
'| iter() | REQ | REQ | yes | yes |\n' +
144+
'| contains() | yes | yes | yes | yes |\n' +
145+
'| len() | | REQ | REQ | REQ |\n' +
146+
'| getitem() | | | REQ | REQ |\n' +
147+
'| reversed() | | | yes | yes |\n' +
148+
'| reverse() | | | | yes |\n' +
149+
'| index() | | | | yes |\n' +
150+
'| count() | | | | yes |\n' +
147151
'+------------+----------+------------+----------+--------------+\n';
148152

149153
const DIAGRAM_7_B =

0 commit comments

Comments
 (0)