JulienPalard / Pipe

A Python library to use infix notation in Python
MIT License
1.95k stars 113 forks source link

Pipes with Context #82

Closed vsraptor closed 2 years ago

vsraptor commented 2 years ago

how would i do in addition to the iterator to have a context :


@Pipe
def foo(it, ctx): ....

still use it like :

... | foo | bar | ...

JulienPalard commented 2 years ago

As | foo(ctx="hello") would work, calling foo(ctx="hello") beforehand and reusing its result should work too, à la:

    bar = foo(ctx="hello")
    ... | bar | ...

Full working demo:

>>> from pipe import Pipe
>>> @Pipe
... def foo(it, ctx):
...     print(ctx)
...     yield from it
... 
>>> bar = foo(ctx="youpi")
>>> list(range(10) | bar)
youpi
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

More info in the README: https://github.com/JulienPalard/Pipe#partial-pipes

vsraptor commented 2 years ago

how do I persist ctx across the pipes i.e. ctx is like state information passed around that can be updated..


@Pipe
def foo(it, ctx): ....
@Pipe
def bar(it, ctx): ....
@Pipe
def baz(it, ctx): ....
JulienPalard commented 2 years ago

Just store your state information in a class (or a list or whatever that can keep a reference to your value), pass this container as the context, keep a reference to this container for later updates.

A bit like you would do a global mutable value without the global keyword::

>>> from pipe import Pipe
>>> class State:
...     ...
... 
>>> @Pipe
... def foo(it, ctx):
...     print(ctx.value)
...     yield from it
... 
>>> state = State()
>>> state.value = 42
>>> with_ctx = foo(ctx=state)
>>> list(range(10) | with_ctx)
42
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> state.value = 43
>>> list(range(10) | with_ctx)
43
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Bonus of this method: your shared state is conveniently stored as properly named attributes in a properly named class that can have its own checkers, init, repr, and so on (as it should be).