PyoIterable
Bases: Pipeable, Checkable, Iterable[T], ABC
flowchart TD
pyochain.abc._iterable.PyoIterable[PyoIterable]
pyochain.rs.Pipeable[Pipeable]
pyochain.rs.Into[Into]
pyochain.rs.Inspect[Inspect]
pyochain.rs.Checkable[Checkable]
pyochain.rs.Pipeable --> pyochain.abc._iterable.PyoIterable
pyochain.rs.Into --> pyochain.rs.Pipeable
pyochain.rs.Inspect --> pyochain.rs.Pipeable
pyochain.rs.Checkable --> pyochain.abc._iterable.PyoIterable
click pyochain.abc._iterable.PyoIterable href "" "pyochain.abc._iterable.PyoIterable"
click pyochain.rs.Pipeable href "" "pyochain.rs.Pipeable"
click pyochain.rs.Into href "" "pyochain.rs.Into"
click pyochain.rs.Inspect href "" "pyochain.rs.Inspect"
click pyochain.rs.Checkable href "" "pyochain.rs.Checkable"
Base ABC for all pyochain Iterables.
It's the common API surface shared by:
- eager
Collections:Seq,Vec,Set,SetMut,Dict - lazy
Iterator:Iter
It extends the standard Iterable[T] protocol, as well as Pipeable and Checkable.
All concrete subclasses must implement __iter__().
Note
The difference between an Iterable and an Iterator is often misunderstood, but it's actually quite simple.
An Iterable is any object that can create an Iterator.
It's sole responsbility is to provide an __iter__ method.
This method must return an object that have a __next__ method, which is the actual Iterator.
An Iterator is an object that can produce elements one at a time, and can be exhausted.
When you do a for x in my_iterable, Python implicitly calls my_iterable.__iter__(), and then repeatedly callsnext()on the resultingIterator` to get the elements.
More concretely, a list, for example, is an Iterable.
You can't call next() on a list, because it don't know how to produce elements by itself, it's primary responsibility being to store them.
However, as soon as you call map(my_list), [x for x in my_list], (*my_list), or any other operation that needs to visit elements, an Iterator is created (implicitly or explicitly) from the list.
It's also why abc::Iterator::__iter__ returns Self by convention.
Example
Since it's very straightforward to implement, it can very easily be integrated into business logic classes to provide them with a rich set of methods for free.
>>> from pyochain.abc import PyoIterable
>>> from dataclasses import dataclass
>>>
>>> @dataclass(slots=True)
... class ClientRegistry(PyoIterable[str]):
... clients: list[str]
...
... def __iter__(self):
... return iter(self.clients)
>>>
>>> registry = ClientRegistry(["Alice", "Bob", "Charlie"])
>>> registry.iter().all(lambda name: name.startswith("A"))
False
>>> registry.iter().join(", ")
'Alice, Bob, Charlie'
>>> registry.iter().map(str.lower).join(", ")
'alice, bob, charlie'
>>> registry.ok_or("Registry is empty").map(lambda s: s.iter().join(", "))
Ok('Alice, Bob, Charlie')
Source code in src/pyochain/abc/_iterable.py
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 | |
first()
Return the first element of the Iterable.
By default, this method convert the Iterable to an Iterator and returns the first element by calling next() on it.
On PyoSequence and its subclasses (Seq, Range, etc.), this is overriden to directly use an efficient __getitem__ access.
If you already are using an Iter, prefer Iter.next() instead, which returns an Option[T] to handle exhaustion gracefully.
Returns:
| Name | Type | Description |
|---|---|---|
T |
T
|
The first element of the |
Example
>>> from pyochain import Seq
>>> data = Seq((1, 2))
>>> data.first()
1
>>> iterator = data.iter()
>>> iterator.first()
1
>>> iterator.first()
2
>>> # iterator is now empty, using first again would raise an error
>>> iterator.next()
NONE
Source code in src/pyochain/abc/_iterable.py
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 | |
iter()
Get an Iter over the Iterable.
Call this to switch to lazy evaluation.
Note
Calling this method on a class who is itself an Iterator has no effect.
Returns:
| Type | Description |
|---|---|
Iter[T]
|
Iter[T]: An |
Example
>>> from pyochain import Seq
>>> seq = Seq((1, 2, 3))
>>> iterator = seq.iter()
>>> iterator.collect()
Seq(1, 2, 3)
>>> # iterator is now empty
>>> iterator.collect()
Seq()
Source code in src/pyochain/abc/_iterable.py
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 | |
last()
Return the last element of the Iterable.
This is similar to __getitem__ but works on lazy Iterators.
Returns:
| Name | Type | Description |
|---|---|---|
T |
T
|
The last element of the |
Example
>>> from pyochain import Seq
>>> Seq((7, 8, 9)).last()
9
Source code in src/pyochain/abc/_iterable.py
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | |