Skip to content

Commit a6658ba

Browse files
committed
Iterable duck types
1 parent 0551097 commit a6658ba

File tree

3 files changed

+155
-134
lines changed

3 files changed

+155
-134
lines changed

README.md

Lines changed: 81 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,7 +1082,7 @@ class MyHashable:
10821082
```
10831083

10841084
### Sortable
1085-
* **With 'total_ordering' decorator you only need to provide one of lt(), gt(), le() or ge() special methods.**
1085+
* **With 'total_ordering' decorator you only need to provide eq() and one of lt(), gt(), le() or ge() special methods.**
10861086
```python
10871087
from functools import total_ordering
10881088

@@ -1100,73 +1100,6 @@ class MySortable:
11001100
return NotImplemented
11011101
```
11021102

1103-
### Iterable
1104-
* **Only required method for iterable is iter(), that should return an iterator of its contents.**
1105-
```python
1106-
class MyIterable:
1107-
def __init__(self, a):
1108-
self.a = a
1109-
def __iter__(self):
1110-
for el in self.a:
1111-
yield el
1112-
```
1113-
1114-
### Collection
1115-
* **Every collection is also an iterable.**
1116-
* **This cheatsheet actually means `'<iterable>'` when it uses `'<collection>'`.**
1117-
* **I chose not to use the name iterable because it sounds scarier and more vague than collection.**
1118-
```python
1119-
class MyCollection:
1120-
def __init__(self, a):
1121-
self.a = a
1122-
def __iter__(self):
1123-
for el in self.a:
1124-
yield el
1125-
def __len__(self):
1126-
return len(self.a)
1127-
def __contains__(self, el):
1128-
return el in self.a
1129-
```
1130-
1131-
### Sequence
1132-
* **Every sequence is also an iterable.**
1133-
* **That is because iter() is automatically generated if getitem() is defined.**
1134-
```python
1135-
class MySequence:
1136-
def __init__(self, a):
1137-
self.a = a
1138-
def __len__(self):
1139-
return len(self.a)
1140-
def __getitem__(self, i):
1141-
return self.a[i]
1142-
```
1143-
1144-
### Collections.abc.Sequence
1145-
* **A much richer interface than the basic sequence.**
1146-
* **Extending it generates contains(), iter(), reversed(), index(), and count().**
1147-
* **It is not a duck type, so `'issubclass(MySequence, collections.abc.Sequence)'` would return 'False' even if it had all the methods defined.**
1148-
```python
1149-
class MyAbcSequence(collections.abc.Sequence):
1150-
def __init__(self, a):
1151-
self.a = a
1152-
def __len__(self):
1153-
return len(self.a)
1154-
def __getitem__(self, i):
1155-
return self.a[i]
1156-
```
1157-
1158-
#### Table of the methods that each (duck) type provides:
1159-
```text
1160-
+------------+----------+------------+----------+--------------+
1161-
| | Iterable | Collection | Sequence | abc.Sequence |
1162-
+------------+----------+------------+----------+--------------+
1163-
| iter() | yes | yes | yes | yes |
1164-
| len() | | yes | yes | yes |
1165-
| getitem() | | | yes | yes |
1166-
| contains() | | yes | | yes |
1167-
+------------+----------+------------+----------+--------------+
1168-
```
1169-
11701103
### Iterator
11711104
```python
11721105
class Counter:
@@ -1235,6 +1168,86 @@ con = sqlite3.connect('<path>'); with con: con.execute('<insert_query>')
12351168
```
12361169

12371170

1171+
Iterable Duck Types
1172+
-------------------
1173+
1174+
### 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.**
1177+
```python
1178+
class MyIterable:
1179+
def __init__(self, a):
1180+
self.a = a
1181+
def __iter__(self):
1182+
for el in self.a:
1183+
yield el
1184+
```
1185+
1186+
```python
1187+
>>> a = MyIterable([1, 2, 3])
1188+
>>> iter(a)
1189+
<generator object MyIterable.__iter__ at 0x1026c18b8>
1190+
>>> 1 in a
1191+
True
1192+
```
1193+
1194+
### Collection
1195+
* **Every collection is also an iterable.**
1196+
* **This cheatsheet actually means `'<iterable>'` when it uses `'<collection>'`.**
1197+
* **I chose not to use the name iterable because it sounds scarier and more vague than collection.**
1198+
```python
1199+
class MyCollection:
1200+
def __init__(self, a):
1201+
self.a = a
1202+
def __contains__(self, el):
1203+
return el in self.a
1204+
def __len__(self):
1205+
return len(self.a)
1206+
def __iter__(self):
1207+
for el in self.a:
1208+
yield el
1209+
```
1210+
1211+
### Sequence
1212+
* **Every sequence is also a collection.**
1213+
* **Iter() and reversed() are automatically generated whenever getitem() is present.**
1214+
```python
1215+
class MySequence:
1216+
def __init__(self, a):
1217+
self.a = a
1218+
def __getitem__(self, i):
1219+
return self.a[i]
1220+
def __len__(self):
1221+
return len(self.a)
1222+
```
1223+
1224+
### Collections.abc.Sequence
1225+
* **It's a richer interface than the basic sequence.**
1226+
* **Extending it generates contains(), iter(), reversed(), index(), and count().**
1227+
* **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.**
1228+
```python
1229+
class MyAbcSequence(collections.abc.Sequence):
1230+
def __init__(self, a):
1231+
self.a = a
1232+
def __getitem__(self, i):
1233+
return self.a[i]
1234+
def __len__(self):
1235+
return len(self.a)
1236+
```
1237+
1238+
#### Table of the methods that each (duck) type provides:
1239+
```text
1240+
+------------+----------+------------+----------+--------------+
1241+
| | Iterable | Collection | Sequence | abc.Sequence |
1242+
+------------+----------+------------+----------+--------------+
1243+
| iter() | yes | yes | yes | yes |
1244+
| len() | | yes | yes | yes |
1245+
| getitem() | | | yes | yes |
1246+
| contains() | | yes | | yes |
1247+
+------------+----------+------------+----------+--------------+
1248+
```
1249+
1250+
12381251
Enum
12391252
----
12401253
```python

0 commit comments

Comments
 (0)