Skip to content

Seq

Bases: PyoSequence[T]


              flowchart TD
              pyochain._seq.Seq[Seq]
              pyochain.abc._sequences.PyoSequence[PyoSequence]
              pyochain.abc._collection.PyoCollection[PyoCollection]
              pyochain.abc._iterable.PyoIterable[PyoIterable]
              pyochain.rs.Fluent[Fluent]
              pyochain.rs.Pipe[Pipe]
              pyochain.rs.Tap[Tap]
              pyochain.rs.Checkable[Checkable]
              pyochain.abc._collection.PyoContainer[PyoContainer]
              pyochain.abc._collection.PyoSized[PyoSized]
              pyochain.abc._sequences.PyoReversible[PyoReversible]

                              pyochain.abc._sequences.PyoSequence --> pyochain._seq.Seq
                                pyochain.abc._collection.PyoCollection --> pyochain.abc._sequences.PyoSequence
                                pyochain.abc._iterable.PyoIterable --> pyochain.abc._collection.PyoCollection
                                pyochain.rs.Fluent --> pyochain.abc._iterable.PyoIterable
                                pyochain.rs.Pipe --> pyochain.rs.Fluent
                
                pyochain.rs.Tap --> pyochain.rs.Fluent
                

                pyochain.rs.Checkable --> pyochain.abc._iterable.PyoIterable
                

                pyochain.abc._collection.PyoContainer --> pyochain.abc._collection.PyoCollection
                
                pyochain.abc._collection.PyoSized --> pyochain.abc._collection.PyoCollection
                

                pyochain.abc._sequences.PyoReversible --> pyochain.abc._sequences.PyoSequence
                



              click pyochain._seq.Seq href "" "pyochain._seq.Seq"
              click pyochain.abc._sequences.PyoSequence href "" "pyochain.abc._sequences.PyoSequence"
              click pyochain.abc._collection.PyoCollection href "" "pyochain.abc._collection.PyoCollection"
              click pyochain.abc._iterable.PyoIterable href "" "pyochain.abc._iterable.PyoIterable"
              click pyochain.rs.Fluent href "" "pyochain.rs.Fluent"
              click pyochain.rs.Pipe href "" "pyochain.rs.Pipe"
              click pyochain.rs.Tap href "" "pyochain.rs.Tap"
              click pyochain.rs.Checkable href "" "pyochain.rs.Checkable"
              click pyochain.abc._collection.PyoContainer href "" "pyochain.abc._collection.PyoContainer"
              click pyochain.abc._collection.PyoSized href "" "pyochain.abc._collection.PyoSized"
              click pyochain.abc._sequences.PyoReversible href "" "pyochain.abc._sequences.PyoReversible"
            

Represent an in memory Sequence.

Implements the Sequence Protocol from collections.abc, as well as PyoSequence.

This class is notably the default return type of [Iter::collect][pyochain._iter.Iter.collect].

The underlying data structure is an immutable tuple, hence the memory efficiency is better than a Vec.

Tip

Seq(tuple) is preferred over Seq(list) as this is a no-copy operation (Python optimizes tuple creation from another tuple).

If you have an existing list, consider using Vec::from_ref instead to avoid unnecessary copying.

If you need immediate iteration anyway, you can directly use Iter instead.

Parameters:

Name Type Description Default
data Iterable[T]

The data to initialize the Seq with.

required
Example
>>> from pyochain import Seq
>>> Seq(())
Seq()
>>> t = (1, 2, 3)
>>> seq = Seq(t)
>>> seq
Seq(1, 2, 3)
>>> seq_2 = Seq(seq.inner)
>>> # No copy is made when creating seq_2 from seq.inner, they reference the same underlying tuple.
>>> is_no_copy = (
...     seq.inner is seq_2.inner
...     and seq.inner is t
...     and seq_2.inner is t
...     and tuple(seq.inner) is t
... )
>>> is_no_copy
True
>>> # However, creating a new Seq from seq (not using .inner) will be a copy operation.
>>> Seq(seq).inner is seq.inner
False
Source code in src/pyochain/_seq.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
153
154
155
156
157
158
159
160
class Seq[T](PyoSequence[T]):
    """Represent an in memory `Sequence`.

    Implements the `Sequence` Protocol from `collections.abc`, as well as `PyoSequence`.

    This class is notably the default return type of [`Iter::collect`][Iter.collect].

    The underlying data structure is an immutable `tuple`, hence the memory efficiency is better than a [`Vec`][Vec].

    Tip:
        `Seq(tuple)` is preferred over `Seq(list)` as this is a no-copy operation (Python optimizes `tuple` creation from another `tuple`).

        If you have an existing `list`, consider using [`Vec::from_ref`][Vec.from_ref] instead to avoid unnecessary copying.

        If you need immediate iteration anyway, you can directly use [`Iter`][Iter] instead.

    Args:
        data (Iterable[T]): The data to initialize the Seq with.

    Example:
        ```python
        >>> from pyochain import Seq
        >>> Seq(())
        Seq()
        >>> t = (1, 2, 3)
        >>> seq = Seq(t)
        >>> seq
        Seq(1, 2, 3)
        >>> seq_2 = Seq(seq.inner)
        >>> # No copy is made when creating seq_2 from seq.inner, they reference the same underlying tuple.
        >>> is_no_copy = (
        ...     seq.inner is seq_2.inner
        ...     and seq.inner is t
        ...     and seq_2.inner is t
        ...     and tuple(seq.inner) is t
        ... )
        >>> is_no_copy
        True
        >>> # However, creating a new Seq from seq (not using .inner) will be a copy operation.
        >>> Seq(seq).inner is seq.inner
        False

        ```
    """

    __slots__ = ("_inner",)  # pyright: ignore[reportUnannotatedClassAttribute, reportIncompatibleUnannotatedOverride]
    _inner: Final[tuple[T, ...]]

    def __init__(self, data: Iterable[T]) -> None:
        self._inner = tuple(data)

    @override
    def __iter__(self) -> Iterator[T]:
        return iter(self._inner)

    @override
    def __repr__(self) -> str:
        return f"{self.__class__.__name__}({get_repr(self._inner)})"

    @override
    def __len__(self) -> int:
        return len(self._inner)

    @overload
    def __getitem__(self, index: int) -> T: ...
    @overload
    def __getitem__(self, index: slice) -> Sequence[T]: ...
    @override
    def __getitem__(self, index: int | slice[Any, Any, Any]) -> T | Sequence[T]:  # pyright: ignore[reportExplicitAny]
        return self._inner.__getitem__(index)

    @override
    def __eq__(self, other: object) -> bool:
        match other:
            case Seq():
                return self._inner == other._inner  # pyright: ignore[reportUnknownMemberType]
            case tuple():
                return self._inner == other
            case _:
                return False

    @override
    def __hash__(self) -> int:
        return hash(self._inner)

    @property
    @no_doctest
    def inner(self) -> tuple[T, ...]:
        """Get the underlying `tuple` data structure.

        Useful when interoperating with functions that require a standard Python `tuple`.

        Returns:
            tuple[T, ...]: The underlying tuple.
        """
        return self._inner

    def repeat(self, n: int) -> Self:
        """Repeat the `Seq` **n** times and return a new `Seq`.

        This is equivalent to `tuple_1 * n` for standard tuples.

        Args:
            n (int): The number of times to repeat the elements.

        Returns:
            Self: The new `Seq` after repetition.

        Example:
            ```python
            >>> from pyochain import Seq
            >>> s = Seq((1, 2, 3))
            >>> s.repeat(2)
            Seq(1, 2, 3, 1, 2, 3)

            ```
        """
        return self.__class__(self._inner * n)

    def concat(self, other: tuple[T, ...] | Self) -> Self:
        """Concatenate another `Seq` or `tuple` to **self** and return a new `Seq`.

        This is equivalent to `tuple_1 + tuple_2` for standard tuples.

        Args:
            other (tuple[T, ...] | Self): The other `Seq` to concatenate.

        Returns:
            Self: The new `Seq` after concatenation.

        Example:
            ```python
            >>> from pyochain import Seq
            >>> s1 = Seq((1, 2, 3))
            >>> s2 = (4, 5, 6)  # Can also concatenate a standard tuple
            >>> s3 = s1.concat(s2)
            >>> s3
            Seq(1, 2, 3, 4, 5, 6)

            ```
        """
        match other:
            case Seq():
                data = self._inner + other._inner
            case tuple():
                data = self._inner + other
        return self.__class__(data)

inner property

Get the underlying tuple data structure.

Useful when interoperating with functions that require a standard Python tuple.

Returns:

Type Description
tuple[T, ...]

tuple[T, ...]: The underlying tuple.

concat(other)

Concatenate another Seq or tuple to self and return a new Seq.

This is equivalent to tuple_1 + tuple_2 for standard tuples.

Parameters:

Name Type Description Default
other tuple[T, ...] | Self

The other Seq to concatenate.

required

Returns:

Name Type Description
Self Self

The new Seq after concatenation.

Example
>>> from pyochain import Seq
>>> s1 = Seq((1, 2, 3))
>>> s2 = (4, 5, 6)  # Can also concatenate a standard tuple
>>> s3 = s1.concat(s2)
>>> s3
Seq(1, 2, 3, 4, 5, 6)
Source code in src/pyochain/_seq.py
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
def concat(self, other: tuple[T, ...] | Self) -> Self:
    """Concatenate another `Seq` or `tuple` to **self** and return a new `Seq`.

    This is equivalent to `tuple_1 + tuple_2` for standard tuples.

    Args:
        other (tuple[T, ...] | Self): The other `Seq` to concatenate.

    Returns:
        Self: The new `Seq` after concatenation.

    Example:
        ```python
        >>> from pyochain import Seq
        >>> s1 = Seq((1, 2, 3))
        >>> s2 = (4, 5, 6)  # Can also concatenate a standard tuple
        >>> s3 = s1.concat(s2)
        >>> s3
        Seq(1, 2, 3, 4, 5, 6)

        ```
    """
    match other:
        case Seq():
            data = self._inner + other._inner
        case tuple():
            data = self._inner + other
    return self.__class__(data)

repeat(n)

Repeat the Seq n times and return a new Seq.

This is equivalent to tuple_1 * n for standard tuples.

Parameters:

Name Type Description Default
n int

The number of times to repeat the elements.

required

Returns:

Name Type Description
Self Self

The new Seq after repetition.

Example
>>> from pyochain import Seq
>>> s = Seq((1, 2, 3))
>>> s.repeat(2)
Seq(1, 2, 3, 1, 2, 3)
Source code in src/pyochain/_seq.py
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
def repeat(self, n: int) -> Self:
    """Repeat the `Seq` **n** times and return a new `Seq`.

    This is equivalent to `tuple_1 * n` for standard tuples.

    Args:
        n (int): The number of times to repeat the elements.

    Returns:
        Self: The new `Seq` after repetition.

    Example:
        ```python
        >>> from pyochain import Seq
        >>> s = Seq((1, 2, 3))
        >>> s.repeat(2)
        Seq(1, 2, 3, 1, 2, 3)

        ```
    """
    return self.__class__(self._inner * n)